Как добавить JNI (собственный код C/С++) в существующий проект Android Studio

Как говорится в заголовке - как добавить собственный код в существующий проект Android Studio, не нарушая текущий проект, включая gradle и настройки proguard?

Ответ 1

Выполните следующие действия из вашего существующего проекта:

1. Измените build.gradle (приложение-модуль), чтобы оно выглядело так (много изменений!):

    apply plugin: 'com.android.model.application'

    model {
        android.signingConfigs {
            create ("myConfig") {
                keyAlias '--your-key-alias--'
                keyPassword '--key-password--'
                storeFile file('--/path/to/keystore.jks--')
                storePassword '--store-password--'
            }
        }
        android {
            compileSdkVersion 25
            buildToolsVersion '25.0.2'

            defaultConfig {
                applicationId "--your.app.name--"
                minSdkVersion.apiLevel 19
                targetSdkVersion.apiLevel 25
                versionCode 1
                versionName "1.0"
            }
            buildTypes {
                release {
                    minifyEnabled true
                    proguardFiles.add(file('proguard-android-optimize.txt'))
                    proguardFiles.add(file('proguard-rules.pro'))
                    signingConfig = $("android.signingConfigs.myConfig")
                }
            }
            ndk {
                moduleName "--c-file--"
                ldLibs.addAll(["android", "log"])
            }

        }
        android.dexOptions {
            javaMaxHeapSize "2048m"
        }
    }

    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        testCompile 'junit:junit:4.12'
        compile 'com.android.support:appcompat-v7:25.3.1'
    }

Вы можете скопировать/вставить приведенный выше код и изменить, по крайней мере, значения с помощью "--value--", чтобы они соответствовали вашим.

2. Измените build.gradle (Проект)

где написано примерно так:

dependencies {
    classpath 'com.android.tools.build:gradle:2.3.3'
}

к этому:

dependencies {
    classpath 'com.android.tools.build:gradle-experimental:0.9.3'
}

Число в моем примере 0.9.3 - последняя версия gradle-экспериментальной, которую можно найти здесь. В конце концов измените версию Gradle в gradle-wrapper.properties на версию, рекомендованную Android Studio, если вы этого еще не сделали.

3. Переместите ваш файл настроек Proguard

proguard-android-optimize.txt в app/proguard-android-optimize.txt

4. Добавить звонок из Java

как это

static {
    System.loadLibrary("--c-file--");
}
private native byte my_jni(Context context, byte[] mByte, int i);

меняется в соответствии с вашими потребностями. В приведенном выше примере загружается c файл (запишите его без расширения) - тот же, который объявлен в файле gradle, и вызывает функцию my_jni, передавая контекст приложения, некоторый байтовый массив и некоторый int, ожидая, что функции возвращают байт,

5. Создайте функцию в JNI:

Теперь название вашей функции выделено красным - позвольте Android Studio создать его. Create function... нажав на красную лампочку в строке. Это создает функцию в вашем файле c и меняет фокус на нее.

Готово

Дальнейшее чтение здесь.

Подсказки:

  • Позаботьтесь о том, чтобы free все, что вы используете malloc, ReleaseByteArrayElements для каждого GetByteArrayElements и т.д.

  • Позаботьтесь о том, как правильно вернуть некоторые опасные значения из C в Java, такие как массивы и строки

Ответ 2

Начиная с Android Studio 3.1 это возможно простым способом:

1. Создайте папку cpp внутри app\src\main.

2. Создайте файл <YOUR_FILE_NAME>.cpp папке app\src\main\cpp (например, native-lib.cpp).

3. Добавьте файл CMakeLists.txt в папку app.

В этом имени файла библиотеки должны быть определены путь к файлу .cpp и некоторые другие параметры, например (из нового пустого Android Studio Project с поддержкой C++):

# 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).
             src/main/cpp/native-lib.cpp )
                          ^^^^^^^^^^^^^^
                          YOUR_CPP_FILE_NAME

# 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

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

4. Добавьте в build.gradle (приложение-модуль) тег externalNativeBuild со ссылкой на CMakeLists.txt в раздел android :

android {
    compileSdkVersion 26
    defaultConfig {
        ...
    }
    buildTypes {
        ...
    }
    externalNativeBuild {               <--- these lines should be added
        cmake {                         <--- these lines should be added
            path "CMakeLists.txt"       <--- these lines should be added
        }                               <--- these lines should be added
    }                                   <--- these lines should be added
}

5. Добавьте в build.gradle (приложение-модуль) тег externalNativeBuild тегом cmake в раздел defaultConfig :

...
defaultConfig {
    applicationId "<YOUR_APP_ID>"
    minSdkVersion 26
    targetSdkVersion 26
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"


    externalNativeBuild {   <--- these lines should be added
        cmake {             <--- these lines should be added
            cppFlags ""     <--- these lines should be added
        }                   <--- these lines should be added
    }                       <--- these lines should be added
}
...

(пример "базового" файла build.gradle также доступного в новом, пустом проекте Android Studio с поддержкой C++)

6. Resync Project с файлами Gradle

Нажав Sync Project Sync Project button on Toolbar на панели инструментов. NB! В Android Studio 3.3 это значок Android Studio 3.3 Sync Project button on Toolbar.

Кроме того, взгляните на официальный учебник.