NDK环境搭建

JNI(Java Native Interface)是java与C/C进行通信的一种技术,使用JNI技术,可以java调用C/C的函数对象等等,Android中的Framework层与Native层就是采用的JNI技术。如果我们程序也需要调用自己的C/C++函数库,就必须用到JNI/NDK开发。Android Studio2.2版本已经完全支持ndk开发了。而且默认采用CMake方式。

那么CMake有哪些优势呢?

  1. 可以直接的在C/C++代码中加入断点,进行调试
  2. java引用的C/C++中的方法,可以直接ctrl+左键进入
  3. 对于include的头文件,或者库,也可以直接的进入
  4. 不需要配置命令行操作,手动的生成头文件,不需要配置android.useDeprecatedNdk=true 属性
下面就是我们第一次写NDK的一些详细步骤:

第一步:下载NDK


第二步:新建工程,勾选上include选项

我们来看看新生成的项目,对一些生成的项目进行具体的解释一下。


上图中红框部分是新建一个NDK项目后自动生成的目录。

  1. .externalNativeBuild文件夹:cmake编译好的文件, 显示支持的各种硬件等信息。系统生成。

  2. cpp文件夹:存放C/C++代码文件,native-lib.cpp文件是默认生成的,可更改。需要自己编写

  3. CMakeLists.txt文件:CMake脚本配置的文件。需要自己配置编写。

下面的app/build.gradle文件也和我们普通的项目的build不同。 app/build.gradle: 


如果我们在新建工程的时候选择的是C11的标准的时候,则cppFlags = "-std=c11"

externalNativeBuild {
     cmake {
         cppFlags "-std=c++11"
     }
 }
CMakeLists.txt配置文件,#开头的全是注释
cmake_minimum_required(VERSION 3.4.1) #指定cmake版本

add_library( #生成函数库的名字
             native-lib

             #生成动态函数看
             SHARED

             #依赖的cpp文件
             src/main/cpp/native-lib.cpp )


find_library( #设置path变量的名称
              log-lib

              #指定要查询库的名字
              log )#在ndk开发包中查询liblog.so函数库(默认省略lib和.so),路径赋值给log-lib

# 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( #目标库,和上面生成的函数库名字一至
                       native-lib

                      #连接的库,根据log-lib变量对应liblog.so函数库
                       ${log-lib} )
新建工程生成的java代码:

public class MainActivity extends AppCompatActivity {

    // 加载函数库
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = (TextView) findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
    }

    /**本地方法, 当前方法是通过C/C++代码实现*/
    //这里的stringFromJNI()方法用native关键字修饰,这个方法是通过C/C++代码实现的。
    public native String stringFromJNI();
}
生成的C++代码:
#include <jni.h>
#include <string>

extern "C"
JNIEXPORT jstring JNICALL
//这里定义的函数名是固定写法
//Java_包名_类名_Java中方法名
//通过这种命名方式就可以唯一对应到java中具体的方法
Java_mjoys_com_ndkdemo01_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "这是Java调用的C++代码";
    return env->NewStringUTF(hello.c_str());
}

第三步:运行项目
我们每次写完C/C++代码,如想要运行项目需要先进行编译,再运行。


我们写好的项目都会生成一个个默认的debug模式下的apk文件,我们来看看这个apk文件,可以直接到目录下去解压该apk文件,也可以利用AS的功能来分析,Build->Analyze APK,我们可以看到在lib文件夹下的x86文件夹下有libnative-lib.so文件。


.so文件是动态函数库,我们写好的C/C++代码默认打包成函数库,就没法看到代码,只能使用了,我们在使用别人编译好的函数库时,只需要根据不同的CPU架构,把函数库放在src/main/jniLib目录下。例如在我的另外一个项目里面。


我们前面都是新建项目生成的默认函数,下面我们自己在MainActivity中写一个Native方法。

public class MainActivity extends AppCompatActivity {

    // 加载函数库
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv1 = (TextView) findViewById(R.id.text1);
        tv1.setText(stringFromJNI());

        TextView tv2 = (TextView) findViewById(R.id.text2);
        tv2.setText(stringFromJNI2());
    }

    /**本地方法, 当前方法是通过C/C++代码实现*/
    //这里的stringFromJNI()方法用native关键字修饰,这个方法是通过C/C++代码实现的。
    public native String stringFromJNI();

    public native String stringFromJNI2();
}
extern "C"
JNIEXPORT jstring JNICALL
Java_mjoys_com_ndkdemo01_MainActivity_stringFromJNI2(JNIEnv *env, jobject instance) {

    std::string output_content = "这是自己写的";

    return env->NewStringUTF(output_content.c_str());
}
最终运行结果:




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值