Android Studio с экспериментальным Gradle плагином и CrystaX NDK
14.12.2015 06:20

Ранее мы описали как использовать CrystaX NDK в Android Studio. С того времени Google анонсировал новый (экпериментальный) Gradle плагин с улучшенной поддержкой NDK в Android Studio. Давайте посмотрим, как использовать CrystaX NDK с этим новым плагином.

Будучи последовательными, мы обновим предыдущую статью, добавив в нее новые условия - т.е. это будет все то же простое UI приложение, использующее Boost.Serialization. Использование Boost необязательно для понимания новой схемы работы с экспериментальным Gradle плагином; тем не менее, мы включили пример работы с Boost для большей полноты примера.

В новом Gradle плагине Google отказался от использования старой, основанной на GNU Make, системы сборки (ndk-build). Теперь для описания каждого аспекта сборки используется Gradle DSL. Это хорошая новость для тех, кто не знаком со старым добрым GNU Make, и желает, чтобы весь процесс сборки целиком контролировался IDE, не заботясь о правке файлов для GNU Make.

Однако у этого подхода есть свои минусы. Наиболее важный - это необходимость разбираться в Gradle DSL и, само собой, уметь хотя бы немного программировать на Groovy.

Давайте посмотрим как это работает.

Java

Первым делом запустите Android Studio и создайте новый Android проект:

Выберите "Android 4.0.3" в качестве целевой версии Android:

Выберите "пустую" activity:

Оставьте все имена как есть и нажмите кнопку "Finish":

Gradle

По умолчанию, Android Studio все еще использует старый Gradle плагин. Давайте переключимся на новый (экспериментальный).

Для начала, откройте и отредактируйте несколько файлов:

build.gradle.diff

gradle/wrapper/gradle-wrapper.properties.diff

app/build.gradle.diff

Теперь нам надо открыть local.properties и добавить путь к CrystaX NDK:

sdk.dir=/opt/android/android-sdk-mac
ndk.dir=/opt/android/crystax-ndk-10.3.1

Пользователям Windows: обратные слэши и двоеточия должны быть экранированы:

sdk.dir=C\:\\android\\android-sdk-mac
ndk.dir=C\:\\android\\crystax-ndk-10.3.1

Теперь нужно синхронизировать изменения в gradle:

Layout

Теперь откройте файл app/res/layout/content_main.xml и поправьте его, чтоб он выглядел так:

content_main.xml.diff
diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml
index ec3933f..077dacc 100644
--- a/app/src/main/res/layout/content_main.xml
+++ b/app/src/main/res/layout/content_main.xml
@@ -13,7 +13,9 @@
     tools:showIn="@layout/activity_main">

     <TextView
+        android:id="@+id/text"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:text="Hello World!" />
+        />
+
 </RelativeLayout>
content_main.xml

MainActivity

Добавьте такие строки в MainActivity.onCreate():

TextView field = (TextView)findViewById(R.id.text);
field.setText(getGPSCoordinates(getFilesDir().getAbsolutePath()));

Добавьте объявление нативного метода в класс MainActivity:

private native String getGPSCoordinates(String rootPath);

Также не забудьте добавить загрузку динамической библиотеки в статический блок инициализации:

static {
    System.loadLibrary("test-boost2");
}

Суммарные изменения:

MainActivity.java.diff
diff --git a/app/src/main/java/net/crystax/examples/testboost2/MainActivity.java b/app/src/main/java/net/crystax/examples/testboost2/MainActivity.java
index f9c0821..0519122 100644
--- a/app/src/main/java/net/crystax/examples/testboost2/MainActivity.java
+++ b/app/src/main/java/net/crystax/examples/testboost2/MainActivity.java
@@ -8,9 +8,16 @@ import android.support.v7.widget.Toolbar;
 import android.view.View;
 import android.view.Menu;
 import android.view.MenuItem;
+import android.widget.TextView;

 public class MainActivity extends AppCompatActivity {

+    static {
+        System.loadLibrary("test-boost2");
+    }
+
+    private native String getGPSCoordinates(String rootPath);
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -26,6 +33,9 @@ public class MainActivity extends AppCompatActivity {
                         .setAction("Action", null).show();
             }
         });
+
+        TextView field = (TextView) findViewById(R.id.text);
+        field.setText(getGPSCoordinates(getFilesDir().getAbsolutePath()));
     }

     @Override

В результате содержимое файла MainActivity.java должно стать таким:

MainActivity.java

Мы закончили заниматься Java-частью приложения; давайте теперь займемся кодом на C++.

C++

Первым делом включим нативную сборку в app/build.gradle:

app/build.gradle.diff

Теперь откроем MainActivity.java и добавим реализацию нативного метода:

Это создаст новый файл app/src/main/jni/test-boost2.c. Переименуем его в app/src/main/jni/test.cpp, а также добавим два новых файла: app/src/main/jni/gps.hpp и app/src/main/jni/gps.cpp.

app/src/main/jni/gps.hpp
app/src/main/jni/gps.cpp
app/src/main/jni/test.cpp

Наконец, добавим новые задачи и вспомогательные функции в app/build.gradle:

app/build.gradle.diff

Структура каталога

Файловое дерево каталога TestBoost2/app должно теперь выглядеть так:

.
├── app.iml
├── build.gradle
├── libs
├── proguard-rules.pro
└── src
    ├── androidTest
    │   └── java
    │       └── net
    │           └── crystax
    │               └── examples
    │                   └── testboost2
    │                       └── ApplicationTest.java
    ├── main
    │   ├── AndroidManifest.xml
    │   ├── java
    │   │   └── net
    │   │       └── crystax
    │   │           └── examples
    │   │               └── testboost2
    │   │                   └── MainActivity.java
    │   ├── jni
    │   │   ├── gps.cpp
    │   │   ├── gps.hpp
    │   │   └── test.cpp
    │   └── res
    │       ├── drawable
    │       ├── layout
    │       │   ├── activity_main.xml
    │       │   └── content_main.xml
    │       ├── menu
    │       │   └── menu_main.xml
    │       ├── mipmap-hdpi
    │       │   └── ic_launcher.png
    │       ├── mipmap-mdpi
    │       │   └── ic_launcher.png
    │       ├── mipmap-xhdpi
    │       │   └── ic_launcher.png
    │       ├── mipmap-xxhdpi
    │       │   └── ic_launcher.png
    │       ├── mipmap-xxxhdpi
    │       │   └── ic_launcher.png
    │       ├── values
    │       │   ├── colors.xml
    │       │   ├── dimens.xml
    │       │   ├── strings.xml
    │       │   └── styles.xml
    │       ├── values-v21
    │       │   └── styles.xml
    │       └── values-w820dp
    │           └── dimens.xml
    └── test
        └── java
            └── net
                └── crystax
                    └── examples
                        └── testboost2
                            └── ExampleUnitTest.java

Конечный результат

Дело сделано! Теперь запустите сборку проекта как обычно (Build -> Make Module 'app') и стартуйте приложение на устройстве или эмуляторе. Ниже приводится снимок экрана с устройства при запущенном приложении:

Пример

Для простоты мы залили готовый к использованию проект на GitHub. Скачивайте и наслаждайтесь!

Back
Home
Map
Back
Home
Map

Наши авторы: