среда, 1 апреля 2015 г.

Валютно-фондовый виджет для Андроид. Курсы валют, акций.

Валютно-фондовый виджет для Андроид

    Привет! 
    Сегодня я расскажу о виджете для Андроид, который показывает курсы валют, биржевые котировки в реальном времени. Если вы следите за биржевыми показателями или просто интересуетесь финансами, то вам он точно будет полезен!

Снимок экрана с виджетом в центре
    
    Чтобы скачать виджет перейдите в Гугл Плей Маркет по ссылке: Google Play Market [currency-and-stock-widget]

    С помощью виджета, вы сможете отслеживать изменение: курса валют, цен на нефть и золото, акций, индексов. А также получать своевременно данные о котировках, которые вам интересны.

    Доступные функции:
    - Выбор и отслеживание множества котировок доступных на сайте http://finance.yahoo.com;    
    - Отслеживание курсов валют;    
    - Получайте обновления ваших финансовых котировок каждую минуту; 
    - Разнообразная цветовая гамма виджета;
    - Динамика изменений финансовых котировок в режиме реального времени. 


Снимок экрана с графиком изменения котировки на нефть марки Брент 

    Чтобы увидеть динамику изменений валют и финансовых котировок просто нажмите на нужную котировку на экране виджета.
    Вы видели как быстро изменился курс доллара с 30 рублей до 60 рублей! А если бы вы вовремя заметили динамики повышения курса доллара, обменяли рубли на доллары, а потом продали, то получили бы прибыль, а ваш деньги увеличились в 2 раза. Именно для этого и был написан этот виджет, поэтому не тратьте время и деньги, а скачивайте Валютно-фондовый виджет, чтобы всегда быть в курсе событий!
    Чтобы скачать виджет перейдите в Гугл Плей Маркет по ссылке: Google Play Market [currency-and-stock-widget]

    Если вам понравился виджет или вы хотите, чтобы добавили еще функций в данный виджет, то сообщите нам об этом, оставив отзыв.
    Чтобы оставить отзыв перейдите по ссылке: 
Оценить [Currency and Stock Widget]

суббота, 17 января 2015 г.

Android Unit тестирование. Настройка Robolectric в Android Studio + Gradle.

Настройка Robolectric в Android Studio не простоя задача, но решаемая!
Что мы имеем в начале:
1 - Установленную Android SDK и последнюю версию Android Studio;
2 - Созданный по умолчанию проект и написано немного код, который нужно тестировать.

    В коде приложения, есть функционал, который зависит от стандартных библиотек Java и может выполняться в JVM(Java Virtual Machine). Значит написанные для него Unit-тесты можно выполнить в самой JVM, без подключения Android устройства или эмулятора. Это ускоряет процесс разработки особенно, если вы используете методологию TDD(Test Driving Development). Для этого я выбрал фреймворк для Unit-тестирования - Robolectric, который используется многими Android разработчиками.
    Robolectric, также позволяет тестировать классы зависящие от Android SDK, такие как: Activity, Fragments и т. д.. И все это без подключения устройства или эмулятора, в вашей JVM!
Это ускоряет процесс разработки, Unit-тесты запускаются без устройства, здорово, не правда ли!? Но есть одна проблемка, чтобы этого добиться, придется повозиться с настройками, да ладно поехали.
    Как только вы создали проект, вы увидите подобную структуру и файл сборки build.gradle, что на рис. 1.
Рисунок 1. Структура приложения в Android Studio
    Перед тем как продолжить, нужно установить Android Studio Unit Test Plugin: https://github.com/evant/android-studio-unit-test-plugin

    После долгих поисков в интернете и неудачных попыток настроить Robolectric для работы в Android Studio, я таки нашел способ все настроить так, чтобы работало.
    Отправной точкой для меня послужил шаблон Android проекта для разработки через тестирование: https://github.com/robolectric/deckard-gradle
    Общий файл сборки build.gradle стал выглядеть так:
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.0.0'

        classpath 'org.robolectric:robolectric-gradle-plugin:0.14.+'

    }
}

allprojects {
    repositories {
        jcenter()
    }
}  

    А файл сборки build.gradle самого Android приложения так:
apply plugin: 'com.android.application'
apply plugin: 'android'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "ru.besttuts.stockwidget"
        minSdkVersion 10
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    sourceSets {
        androidTest {
            setRoot('src/test')
        }
    }
}

apply plugin: 'robolectric'

robolectric {
    include '**/robolectric/**/*Test.class'
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.+'

    androidTestCompile 'org.hamcrest:hamcrest-core:1.3'
    androidTestCompile 'org.hamcrest:hamcrest-library:1.3'

    androidTestCompile('junit:junit:4.12') {
        exclude module: 'hamcrest-core'
    }
    androidTestCompile('org.robolectric:robolectric:2.4') {
        exclude module: 'classworlds'
        exclude module: 'commons-logging'
        exclude module: 'httpclient'
        exclude module: 'maven-artifact'
        exclude module: 'maven-artifact-manager'
        exclude module: 'maven-error-diagnostics'
        exclude module: 'maven-model'
        exclude module: 'maven-project'
        exclude module: 'maven-settings'
        exclude module: 'plexus-container-default'
        exclude module: 'plexus-interpolation'
        exclude module: 'plexus-utils'
        exclude module: 'wagon-file'
        exclude module: 'wagon-http-lightweight'
        exclude module: 'wagon-provider-api'
    }
}

apply plugin: 'idea'

idea {
    module {
        testOutputDir = file('build/test-classes/debug')
    }
}

    Обратите внимание на строки:
    sourceSets {
        androidTest {
            setRoot('src/test')
        }
    }
    По умолчанию Android Studio создает директорию для тестов под названием androidTest, которую понимает среда разработки и подсвечивает соответствующим образом. Чтобы придерживаться стандартов, я переименовал эту директорию в test и указал это среде разработки, как показано выше.
    
    Обратите внимание на строки:
    apply plugin: 'robolectric'

    robolectric {
        include '**/robolectric/**/*Test.class'
    }
    Я создал директорию robolectric (D:\ideaWorkspace\StockWidget\android\src\test\java\ru\besttuts\stockwidget\robolectric\EconomicWidgetConfigureActivityTest.java), в которой будут находиться тесты созданные на базе Robolectric. При выполнении тестов Robolectic будет тестировать откомпилированные классы оканчивающиеся на *Test.class и находящиеся в директории/субдиректориях robolectric, как показано выше.

   Не забываем нажать Sync Now для начала подгрузки зависимостей!

Далее напишем простенький тест (рис. 2), чтобы удостовериться в работоспособности нашей настройки.
Рисунок 2. Простенький Unit-тест для проверки
    Теперь все готово и можно приступить к тестированию; открываем Terminal в Android Studio и вводим:
    gradlew clean test
 
    Результат теста можно посмотреть по адресу: file:///D:/ideaWorkspace/StockWidget/android/build/test-report/debug/index.html, пример которого на рис. 3.
Рисунок 3. Пример результата теста
    Если при выполнение теста из консоли, обычно, проблем не возникает, то из Android Studio возникают ошибки, упоминания о которых полно в интернете.
    Сейчас я опишу путь решения. Поехали.

    Кликаете правой кнопкой по файлу теста -> в раскрывшемся контекстном меню кликаете по Run и выбираете обычный JUnit тест(не Android Test).
    С 99,99% вероятностью Вы получите ошибку:
!!! JUnit version 3.8 or later expected:

java.lang.RuntimeException: Stub!
at junit.runner.BaseTestRunner.<init>(BaseTestRunner.java:5)
at junit.textui.TestRunner.<init>(TestRunner.java:54)
at junit.textui.TestRunner.<init>(TestRunner.java:48)
at junit.textui.TestRunner.<init>(TestRunner.java:41)
    Копируем -classpath "...", рис. 4.
Рисунок 4. Копируем -classpath "..."
    Теперь отредактируем наш -classpath.

-classpath "C:\Program Files\Android\Android Studio\lib\idea_rt.jar;C:\Program Files\Android\Android Studio\plugins\junit\lib\junit-rt.jar;D:\ideaWorkspace\StockWidget\android\build\intermediates\classes\debug;C:\Android\android-sdk\platforms\android-21\android.jar;C:\Android\android-sdk\platforms\android-21\data\res;C:\Users\roman\.gradle\caches\modules-2\files-2.1\org.robolectric\robolectric-annotations\2.4\936c649cb0958d7fb5d3c09b31c56b3997f80650\robolectric-annotations-2.4.jar;...;C:\Users\roman\.gradle\caches\modules-2\files-2.1\com.almworks.sqlite4java\sqlite4java\0.282\745a7e2f35fdbe6336922e0d492c979dbbfa74fb\sqlite4java-0.282.jar"

    Строчку выделенную жирным шрифтом: C:\Android\android-sdk\platforms\android-<21>\android.jar;C:\Android\android-sdk\platforms\android-<21>\data\res; необходимо вырезать и вставить в конец нашего -classpath, и не забывайте ставить разделители ';'.
Вместо <21> может быть другая версия Android SDK, которую вы используете!
 
    После этого, также в конец нужно вставить: ;<D:\ideaWorkspace\StockWidget\>android\build\test-classes; - это путь до ваших откомпилированных тестовых классов вида *Test.class.
<D:\ideaWorkspace\StockWidget\> - вместо этого, вы должны вставить корневой путь до вашего проекта!

   В конце мы получаем наш отредактированный -classpath:
-classpath "C:\Program Files\Android\Android Studio\lib\idea_rt.jar;C:\Program Files\Android\Android Studio\plugins\junit\lib\junit-rt.jar;D:\ideaWorkspace\StockWidget\android\build\intermediates\classes\debug;C:\Users\roman\.gradle\caches\modules-2\files-2.1\org.robolectric\robolectric-annotations\2.4\936c649cb0958d7fb5d3c09b31c56b3997f80650\robolectric-annotations-2.4.jar;...;C:\Users\roman\.gradle\caches\modules-2\files-2.1\com.almworks.sqlite4java\sqlite4java\0.282\745a7e2f35fdbe6336922e0d492c979dbbfa74fb\sqlite4java-0.282.jar;C:\Android\android-sdk\platforms\android-21\android.jar;C:\Android\android-sdk\platforms\android-21\data\res;D:\ideaWorkspace\StockWidget\android\build\test-classes"

    Открываем Edit Configurations... -> находим Run/Debug Configurations настройки для запуска нашего Unit-теста и в VM options копируем наш измененный -classpath, рис. 5.
Рисунок 5. Вставка -classpath в VM options
    Также нужно создать Gradle конфигурацию, которая будет компилировать тестовые классы. Для этого откройте Gradle Tasks находящийся в правой части Android Studio. Среди All Tasks найдите test и запустите ее. Она выполнит тесты, при этом в Run/Debug Configurations появится новая Gradle конфигурация, которая будет запускать команду test, рис. 6.
Рисунок 6. Gradle конфигурация для запуска команды тест
  Перед выполнением нашего теста, нужно выполнить команду test из созданной нами Gradle конфигурации, путем добавления ее в Before Launch: Another Configuration, как показано на рис. 7.
Рисунок 7. Добавления Gradle конфигурации в Before Launch наше Unit-теста

   Нажимаем Apply -> Ok, сохраняем настройки запуска теста.

   Далее запускаем наш тест, и все должно заработать, рис. 8!
Рисунок 8. Наш тест прошел без ошибок
    Если вы добавляете новые зависимости в файл сборки build.gradle, то необходимо их также добавить в -classpath для запуска нашего теста, иначе тест может выбросить ошибку, так как добавленный зависимости на в -classpath(в VM options)!

    Все описал как сам настроил, ничего не забыл надеюсь. Если возникли вопросы пишите, постараюсь ответить. Лучше бы это все в видео формате выложить, чтобы было более понятно, как считаете?

    Спасибо за внимание!