This project has been on hold since 2016.
All the data on this site is still available (and will stay available) but not actual anymore.
You might be interested in checking out Dmitry Moskalchuk's portfolio website to learn about his other projects.
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

Наши авторы: