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 的配合使用
2015.12.14 06:20

之前我们介绍过如何在 Android Studio 中使用 CrystaX NDK 。 前些时候 Google 发布了一个 Android Studio 相关支持 NDK 开发的新(实验性)Gradle插件。 让我们来看看 如何基于这个新插件使用 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" 目标版本:

选择 空白 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()));

添加 native 方法的声明到 MainActivity 类:

private native String getGPSCoordinates(String rootPath);

同样的,别忘记在静态初始化部分添加 native 库的加载逻辑:

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 部分,现在切换到 native 部分。

Native 部分

首先我们在 app/build.gradle 中启用 native 编译:

app/build.gradle.diff

然后打开 MainActivity.java 添加 native 方法的实现:

它会创建 app/src/main/jni/test-boost2.c 文件。 现在把它重命名为 app/src/main/jni/test.cpp ,并添加另外两个文件: app/src/main/jni/gps.hppapp/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 Project) 并在设备上运行它。这里是运行结果的一个截屏:

示例项目

方便起见,我们上传了一份即时可用的项目到 GitHub 。 请随意签出查阅。

Back
Home
Map
Back
Home
Map

Our contributors: