AndroidStudio モジュール内のC++を参照する(Java / kotlin)


Androidでライブラリー作成(AAR形式)はモジュールを作成することで実現します。
ただ、 モジュール内のC++ソース参照はめんどくさいので手順を残します。

■Setp1:プロジェクト作成


「File」「New」「New Project」でプロジェクトを作成します。

C++を使用するので。「Native C++」を選択し「Next」をおします。

今回はNameは「Test02」で
Save Locationは開発するディレクトリを指定
Languageは今回はJavaで(Kotlinでも大丈夫です)設定したら「Next」を

あとは、そのまま「Finish」を

こんな画面になればプロジェクト作成できています。

■Setp2;モジュール作成


Setp1で作ったプロジェクトにモジュールを追加します。
「File」「New」「New Modile」を選択してください。

今回は「Android Library」を選択し、「Next」を

Application/Library nameは今回は「test02module」にしています。
「Finish」を押せば

こんな感じになり、「test02module」がプロジェクトに追加されたことがわかります。

■Setp3:モジュールにC++のソースを追加。

まず、C++のソースを置くディレクトリを作成します。
[test02]
+---[test02modile]
  +---[src]
    +---[main]
      +---[cpp] (このディレクトリを作成)
そこに「CMakeList.txt」「subTest.cpp」「subTest.h」 を作成します。

CMakeList.txt
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
        native-module

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        subTest.cpp)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

set( LIB_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../.. )
set( OUTPUT_DIR ${LIB_ROOT}/lib/${ANDROID_ABI} )
set_target_properties( native-module
        PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_DIR} )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
        native-module

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})
subTest.cpp
#include "subTest.h"

subTest::subTest() {
}

void subTest::Hoge(int in_no) {
    int a = in_no;
}
subTest.h
#pragma once

class subTest{
public:
    subTest();
public:
    void Hoge(int in_no);
};

この三ファイルを追加したらbuild.gradle(Module:test02module)を編集します。

build.gradle
android {
   :
   :
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
}

を追加します。
これでいったんSyncさせると

ファイルがModuleに追加されたことがわかります。

■Setp4:アプリのCからモジュールのCを呼び出す。

アプリ側のbuild.gradle(Module:app)を編集します。

android {
  :
  :
    sourceSets {
        main {
            jniLibs.srcDir '../test02module/src/lib'
            jni.srcDirs = []
        }
    }
}

これで、C++のライブラリsoファイルを参照できるようにします。
アプリ側の「CMakeKists.txt」を編集します。

CMakeKists.txt
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
        native-lib

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        native-lib.cpp)

include_directories(../../../../test02module/src/main/cpp)

add_library( native-module
        SHARED
        IMPORTED )
set_target_properties( native-module
        PROPERTIES IMPORTED_LOCATION
        ../../../../../test02module/src/lib/${ANDROID_ABI}/libnative-module.so)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
        native-lib
        native-module
        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

これで、参照可能になったので。 アプリのCのソースをnative-lib.cpp

native-lib.cpp
#include <jni.h>
#include <string>

#include "subTest.h"

extern "C" JNIEXPORT jstring JNICALL
Java_l_toox_test02_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    subTest ss;
    ss.Hoge(32);
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

で参照できます。

■Step5:コンパイルエラー

そのままコンパイルするとエラーになるときがあります。
それはsoファイルが作成されてないかもしれないので

「test02modile」を選択したあとに「Build」を選択すると「Make Moduke 'test02module'」があらわれるので実行してから、アプリを実行すると問題ないです。