• JNI 在Android Studio利用NDK编译运行一个简单的c库


    NDK开发,其实是为了项目需要调用底层的一些C/C++的一些东西;另外就是为了效率更加高些。如果你在Eclipse+ADT下开发过NDK就能体会到要么是配置NDK还要下载Cygwin,配置Cygwin ,然后需要编译生成,相当的蛋疼。

    在AS中新建一个Project,然后再新建一个class为TestHello,在内部声明native方法(jni使用的定义,后面系列教程会细说)。

    public class TestHello {
        public native static String getCLanguageString();
    
    }

    在工程主文件Activity中写入如下代码调运JNI的东西显示在UI上。

    package com.otherway.myapplication;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.widget.Toast;
    
    public class MainActivity extends AppCompatActivity {
    
        private Toast mToast;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
    
            showTip(TestHello.getCLanguageString());
        }
    
        private void showTip(final String str) {
            mToast.setText(str);
            mToast.show();
        }
    
    }

    然后build project得到其中中间文件,我们关注的是.class文件。编译OK以后生成的class文件在AS工程的如下目录:

    app/build/intermediates/classes/debug
    

    然后接下来的步骤就是根据生成的class文件,利用javah生成对应的 .h头文件。

    点开AS的Terminal标签,默认进入到该项目的app文件夹下。我在ubuntu平台下输入如下命令跳转到class中间文件生成路径:

    cd app/build/intermediates/classes/debug/

    然后执行如下javah命令生成h文件。

    xxxxxdebug> javah -jni com.otherway.myapplication.TestHello

    执行完之后你可以在文件夹app/build/intermediates/classes/debug/下看见生成的 .h头文件为:

    com_otherway_myapplication_TestHello.h

    其内容为:

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

    在工程的main目录下新建一个名字为jni的目录,然后将刚才的 .h文件剪切过来。在jni目录下新建一个c文件,随意取名,我的叫TestHello.c 。然后编辑代码如下(后面会解释啥意思,这里重在工具使用):

    #include "com_otherway_myapplication_TestHello.h"
    /*
     * Class:     com_otherway_myapplication_TestHello
     * Method:    getCLanguageString
     * Signature: ()Ljava/lang/String;
     */
    JNIEXPORT jstring JNICALL Java_com_otherway_myapplication_TestHello_getCLanguageString
      (JNIEnv *, jclass){
         return (*env)->NewStringUTF(env," Android Studio NDK JNI Hello");
      }

    接下来在工程的local.properties文件中添加NDK路径(上面下载好的那个NDK),类似其中的SDK路径一样,我的添加后如下:

    ndk.dir=/home/cam/Android/Sdk/ndk-bundle
    sdk.dir=/home/cam/Android/Sdk

    接下来在app module目录下的build.gradle中设置库文件名(生成的so文件名)。找到gradle文件的defaultConfig这项,在里面添加如下内容:

        defaultConfig {
    
            ndk {
                moduleName "testhello"
                ldLibs "log", "z", "m"  //添加依赖库文件,因为有log打印等
            }
        }

    现在生成的so库名字也有了,那就去代码的TestHello java文件添加静态初始化load代码,添加如下:

        static {
            try {
                System.loadLibrary("testhello");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

     好了,到此AS下NDK JNI开发的代码编写和设置就OK了,接下来就是编译工程运行就可以了。

  • 相关阅读:
    指针和数组的关系
    深入学习数组
    const关键字与指针
    野指针是什么
    指针带来的一些符号的理解
    指针的本质
    内存管理之堆
    内存管理之栈
    元类
    断点调式和面向对象进阶
  • 原文地址:https://www.cnblogs.com/CZM-/p/7943572.html
Copyright © 2020-2023  润新知