美文网首页
Android NDK开发-静态注册JNI Demo(二)

Android NDK开发-静态注册JNI Demo(二)

作者: 家有萌犬 | 来源:发表于2018-08-05 14:34 被阅读0次

    上文我们已经介绍了如何配置android studio环境来开发NDK,本篇实战开发,写一个简单的Demo。

    • MainActivity.java
    public class MainActivity extends AppCompatActivity {
    
        // 用于在应用程序启动时加载“native-lib”库。
        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++实现
        public native String stringFromJNI();
    }
    

    使用上篇介绍的javah -jni命令工具可以生成头com_example_lynnlee_ndkdemo_MainActivity.h文件

    • com_example_lynnlee_ndkdemo_MainActivity.h
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_example_lynnlee_ndkdemo_MainActivity */
    
    #ifndef _Included_com_example_lynnlee_ndkdemo_MainActivity
    #define _Included_com_example_lynnlee_ndkdemo_MainActivity
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_example_lynnlee_ndkdemo_MainActivity
     * Method:    stringFromJNI
     * Signature: ()Ljava/lang/String;
     */
    JNIEXPORT jstring JNICALL Java_com_example_lynnlee_ndkdemo_MainActivity_stringFromJNI
      (JNIEnv *, jobject);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    

    函数名Java_com_example_lynnlee_ndkdemo_MainActivity_stringFromJNI组成:类名_方法名组成。参数JNIEnv *和jobject必须有,JNIEnv之jvm指针,jobject指调用该函数的java类引用。

    在jni目录下新建jnitest.c文件,刚才com_example_lynnlee_ndkdemo_MainActivity.h名字太长,改为jnitest.h。

    //
    // Created by LynnLee on 2018/8/5.
    //
    #include "jnitest.h"
    
    JNIEXPORT jstring JNICALL Java_com_example_lynnlee_ndkdemo_MainActivity_stringFromJNI(JNIEnv *env, jobject obj)
    {
        return (*env)->NewStringUTF(env, "LynnLee");
    }
    

    函数实现就返回了一个"LynnLee"字符串

    在jni目录下新建Android.mk文件,Android.mk文件是Android 的makefile文件

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_MODULE := native-lib
    LOCAL_SRC_FILES := jnitest.c
    include $(BUILD_SHARED_LIBRARY)
    
    • LOCAL_PATH := $(call my-dir)

    宏函数’my-dir’由编译系统提供,返回当前包含Android.mk文件的目录路径

    • include $(CLEAR_VARS)

    CLEAR_VARS由编译系统提供,清除除LOCAL_PATH以外的其它LOCAL_XXX变量

    • LOCAL_MODULE :=native-lib

    编译的目标对象,LOCAL_MODULE变量必须定义,以标识你在Android.mk文件中描述的每个模块。名称必须是唯一的,而且不包含任何空格。
    注意:编译系统会自动产生合适的前缀和后缀,换句话说,一个被命名为native-lib的共享库模块,将会生成'libnative-lib.so'文件。

    • LOCAL_SRC_FILES :=hello-jni.c
      LOCAL_SRC_FILES变量必须包含将要编译打包进模块中的C/C++源代码文件。这里不需要列出头文件和包含文件,因为编译系统将会自动为你找出依赖型的文件,仅仅列出直接传递给编译器的源代码文件就好。

    include $(BUILD_SHARED_LIBRARY)

    指定编译出的库类型1.BUILD_SHARED_LIBRARY:动态库;2.BUILD_STATIC_LIBRARY:静态库;3.BUILD_EXECUTEABLE指:可执行文件

    Application.mk

    APP_ABI := all
    

    APP_ABI有四种类型(默认armeabi),armeabi、armeabi-v7a、x86、mips,设置时以空格隔开,all表示所有。

    生成库

    需要修改app/CMakeLists.txt文件,修改如下:


    CMakeLists.txt.png

    利用上篇创建的ndk -build命令工具生成库


    so库.png

    使用库

    • 1.在main/libs目录下生成的so文件(名字为lib+我们指定的库名)复制到app/libs目录下,并且在gradle添加加载so库的设置,如下代码:
    sourceSets {
            main {
                jniLibs.srcDirs = ['libs']
            }
        }
    
    • 2.删除main目录下jni、libs、obj三个文件夹。修改gradle文件,注释掉如下代码:
    /*externalNativeBuild {
            cmake {
                path "CMakeLists.txt"
            }
        }*/
    

    否则报错:


    错误.png

    gradle修改如下图


    gradle.png
    • 3.然后在Activity中测试调用,在TextView上显示我们通过C++代码实现的方法getPackname获取app的包名了。
    运行效果.png

    git代码路径:https://github.com/lynnleescz/NDKdemo

    相关文章

      网友评论

          本文标题:Android NDK开发-静态注册JNI Demo(二)

          本文链接:https://www.haomeiwen.com/subject/chsbvftx.html