如何将JNI(C/C++本机代码)添加到现有的Android Studio项目中

Vla*_*mir 18 java-native-interface android

就像标题所说 - 如何在不破坏当前项目(包括gradle和proguard设置)的情况下向现有Android Studio项目添加本机代码?

And*_*nko 32

从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} )
Run Code Online (Sandbox Code Playgroud)

4. externalNativeBuild参考CMakeLists.txt以下android部分添加到build.gradle(模块应用程序)标记:

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
}
Run Code Online (Sandbox Code Playgroud)

5.将externalNativeBuild带有cmake标记的build.gradle(Module app)标记添加到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
}
...
Run Code Online (Sandbox Code Playgroud)

("基本" build.gradle文件的示例也可在支持C++的新的空Android Studio项目中使用)

6.使用Gradle文件重新同步项目

单击"同步项目" 工具栏上的 在工具栏中.

另外,看看官方教程.

  • 自从Android Studio(3.3.1)上一次更新以来,我的cpp文件夹为空。是否有关于如何集成本机源文件的更新,或者它是AS中的错误? (2认同)

Vla*_*mir 6

从现有项目中执行以下步骤:

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'
    }
Run Code Online (Sandbox Code Playgroud)

您可以复制/粘贴上面的代码,并使用"--value--"修改至少值以匹配您的值.

2.修改build.gradle(项目)

它说的是这样的:

dependencies {
    classpath 'com.android.tools.build:gradle:2.3.3'
}
Run Code Online (Sandbox Code Playgroud)

对此:

dependencies {
    classpath 'com.android.tools.build:gradle-experimental:0.9.3'
}
Run Code Online (Sandbox Code Playgroud)

我的示例0.9.3中的数字是可在此处找到的最新版本的gradle-experimental .最终改变你的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);
Run Code Online (Sandbox Code Playgroud)

改变你的需求.上面的例子加载了c文件(没有扩展名写入) - 在gradle文件中声明的相同,并调用函数my_jni,传递应用程序的Context,一些字节数组和一些int,期望函数返回一个字节.

5.在JNI中创建函数:

现在,您的功能名称以红色突出显示 - 允许Android Studio Create function ...通过单击行上的红色指示灯来创建它.这将在您的c文件中创建该函数并将焦点更改为它.

完成

进一步阅读这里.

提示:

  • 照顾到free一切你malloc,ReleaseByteArrayElements每一个GetByteArrayElements等

  • 注意如何正确地将一些危险值从C 返回到Java,如数组和字符串


Ami*_*ian 5

现在有一个简单的方法,只需在项目资源管理器中右键单击您的模块,然后单击“将 C++ 添加到模块”:

在此输入图像描述