Android Studio NDK开发全攻略

Catalogue
  1. 1 准备工作
  2. 2 使用NDK开发第一个JNI程序
  3. 3 使用.so文件开发Android程序
  4. 参考资料

读完本章,你可以:

  • 在Android Studio上轻松搭建NDK开发环境。
  • 掌握最快捷的JNI开发方式。
  • 掌握使用.so文件开发Android程序的技巧。

1 准备工作

参考链接>>

2 使用NDK开发第一个JNI程序

  1. 在Android程序中新建一个包含native(本地)方法的NDKTest类。

    1
    2
    3
    4
    5
    6
    7
    8
    package com.lavor.ndklearning;
    public class NDKTest {
    static {
    //加载.so库文件
    System.loadLibrary("lavor");
    }
    public native String getString();
    }

    程序中static{}称为静态代码块,它在类初始化的时候执行。

  2. 将鼠标移动到方法名getString上,然后按下Alt+Enter快捷键,弹出一些解决的方法建议,点击第一个Create Function…

  3. 此时会自动建立一个与java目录同级的jni目录,在jni目录自动建立一个c文件,在c文件中实现了刚才的native方法。

  4. 然后,稍稍修改一下.c文件中实现的native方法。

    1
    2
    3
    4
    5
    JNIEXPORT jstring JNICALL
    Java_com_lavor_ndklearning_NDKTest_getString(JNIEnv *env, jobject instance) {
    // TODO
    return (*env)->NewStringUTF(env, "AndroidStudio NDK开发最佳入门实践");
    }

    仔细观察可以看到c文件的方法名是遵循“Java_包名类名本地方法名”来组织的(了解到这些后,我们就可以脱离编译器的帮助,直接去写.c文件啦)。

  5. 最后在Android程序中调用JNI接口。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class MainActivity extends Activity {
    private android.widget.TextView text;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    this.text = (TextView) findViewById(R.id.text);
    NDKTest NDK=new NDKTest();
    text.setText(NDK.getString());
    }
    }

    运行程序后界面如下:

我们在正式开发时,不会像这样子去开发。因为这样的话就会把我们的c代码也暴露了出来。这明显与JNI的安全保密机制相违背,所以,正式开发的时候,我们会使用.so文件进行全保密式的开发。

3 使用.so文件开发Android程序

不知道大家有没有记得上一章说过,使用JNI有个好处就是安全性高,JNI部分的代码很难被反编译。这其实是要归功于.so文件。下图为.so文件的生成位置。

具体的使用步骤是怎样的呢?

  1. 新建一个Android工程,命名为:AndroidApplication。(工程名、包名、组织名任意)

  2. 导入.so文件至app/libs中。

  3. 为了能够调用libs文件夹下的.so资源,需在app的build.gradle的android节点下设置。

    1
    2
    3
    4
    5
    sourceSets{
    main{
    jniLibs.srcDirs = ['libs']
    }
    }
  4. 新建相关类结构。

    1
    2
    3
    4
    5
    6
    7
    8
    package com.lavor.ndklearning;
    public class NDKTest {
    static {
    //加载.so库文件
    System.loadLibrary("lavor");
    }
    public native String getString();
    }

Android端声明native code的代码需要严格按照JNI接口来组织。(也就是说,包名、类名都要和.so文件中JNI名称一致)不懂就点击这里吧>>

  1. 函数调用。
    1
    2
    3
    4
    5
    6
    7
    8
    public class DemoActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_demo);
    Log.d("NDK",new NDKTest().getString());
    }
    }
    运行结果如下:

注意啦!此文并非原创,算是对一波优秀文章的总结吧。笔者希望通过这种方式激励自己学习,也期待可以帮到正在学习NDK的你。欢迎指出本文的BUG,共勉!!!!!


参考资料

  1. AndroidStudio NDK开发最佳入门实践
  2. 如何在Android中使用编译好的.so库