美文网首页Android-NDK/JNI开发笔记FFmpeg
Android Studio NDK 开发与调试(生成 .so

Android Studio NDK 开发与调试(生成 .so

作者: jarylan | 来源:发表于2016-12-16 19:52 被阅读14700次

    温馨提示:如果你的 Android Studio 版本在 2.2 以上 , 建议你用 cMake 的新姿势进行 NDK 开发 : http://www.jianshu.com/p/e03028f826d7
    我相信你会爱上 cMake 的;

    1. 环境搭建

    俗话说 “工欲善其事,必先利其器” ;所以咱还是得先下载 ndk;
    下载地址 :https://developer.android.com/ndk/downloads/index.html(需要翻墙,你懂得)
    或者可以直接在 Android Studio 里面下载,这就可以免去翻墙,
    File-->Project Structure

    image1.png
    如果你已经下载,直接选择你 ndk 的位置;
    如果没有下载,在红色框这个位置会有位置提示你下载,点击下载就行;
    添加 ndk 后你会在 local.properties 这个文件看到(路径取决于你 ndk 的位置):
    image2.png
    莫慌,还差最后一步:
    image3.png
    在此处加上这句代码:android.useDeprecatedNdk=true
    好了,ndk 环境搭建完毕!
    2. java 代码与 c 代码编写

    首先新建个 java 类

    public class JniTest{
        static {
            System.loadLibrary("jary");
        }
        public native String getString();
    }
    

    然后重新编译下你的 Project: Build-->Make Project(Ctrl+F9)
    重新编译之后就可以在对应的文件夹看到编译后的 JniTest.class
    C:\ASworkspace\MyJniTest\app\build\intermediates\classes\debug\jary\com\myjnitest


    image4.png

    下一步来看怎么生成 .h 的文件
    在 studio 打开 Terminal 命令行工具,打开步骤是 View-->Tool Windows-->Terminal (Alt+F12)

    在命令行中先进入到工程的 main 目录下
    输入命令:javah -d jni -classpath 自己编译后的 class 文件的绝对路径
    例如:javah -d jni -classpath
    C:\ASworkspace\MyJniTest\app\build\intermediates\classes\debug jary.com.myjnitest.JniTest
    注意 debug 后面是有个空格的,如图:

    image5.png

    命令执行后会在 main 目录下(在哪个目录下执行就会在哪个目录下生成 .h 文件)自动生成 “jni” 文件夹,同时生成一个 .h 的文件

    imag6.png

    这个 .h 文件可不做修改 ;默认就行
    现在我们来写一个测试的 C 文件 jary.c 同 .h 文件一样放到 jni 文件夹下,代码如下:


    image7.png

    依赖刚才生成的 .h 头文件 ; 方法名与 .h 里面方法名保持一致 ;
    最后在 build.gradle defaultConfig 中添加如下代码

     ndk {   
            moduleName "jary"         //生成的so名字    
            abiFilters "armeabi", "armeabi-v7a", "x86"  //输出指定三种abi体系结构下的so库。    
            stl "stlport_static"    //打开.c 的 debug , 下面第 4 点会讲到
          }
    

    到这里,jni 调 C 就完成了,现在我们来测试一下,写个 TextView 显示一下调用的 C:

    public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView tvJni = (TextView) findViewById(R.id.tvJni);
        tvJni.setText(new JniTest().getString());
    }
    }
    

    效果如下图 :


    image8.png
    3. 生成 .so 以及调用

    编译后的 .so 文件如下图路径:

    image9.png

    根据这个路径就可以找到指定输出的三种体系结构下的 .so 文件,然后把 .so 文件复制出来,如下图所示的放到 jniLibs 文件夹下面,如下图:

    image10.png

    注意: 放到 jniLibs 文件夹下面,build.gradle 里面什么都可以不用配置

    还有一种方式是将 .so 文件 放在 libs 文件夹下面,注意在 build.gradle 添加如下配置:

    iamge11.png
    4. 关于ndk开发在 .c 文件里面的 debug

    首先在 build.gradle 中添加如下代码 :

    android {
        ... ...
      defaultConfig {
          ... ...
         ndk {   
            moduleName "jary"         //生成的so名字    
            abiFilters "armeabi", "armeabi-v7a", "x86"  //输出指定三种abi体系结构下的so库。    
            stl "stlport_static"    //打开.c 的 debug (此句是打开的debug的关键)
         }
      }
      buildTypes {
         debug {    
                jniDebuggable true //此句不加在真机上 debug 不受影响,但是在虚拟机上不能 debug
         }
      }
    

    配置后如下图 ,会出现一个 app-native,选择此项你就可以尽情的 debug 了:

    image12.png

    debug 如下图:


    image13.png

    相关文章

      网友评论

      • 不死就继续:为什么我执行完了,也有了头文件和.c文件,编译也正确,可build下面就是没有ndk文件夹呢??
        jarylan:可以尝试下执行 Build->Rebuild Project 再查看下有没有 ;
        还不行可以网上找下 AS 用命令生成 .so 文件
        2d0800631804:我也是呀,同问
      • 夏沫丶浅吟:FATAL EXCEPTION: main
        Process: com.my_project, PID: 4880
        java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String com.my_project.test_jni.interfaces.SimpleJNIinterface.sayName() (tried Java_com_my_1project_test_1jni_interfaces_SimpleJNIinterface_sayName and Java_com_my_1project_test_1jni_interfaces_SimpleJNIinterface_sayName__)
        at com.my_project.test_jni.interfaces.SimpleJNIinterface.sayName(Native Method)
        at com.my_project.test_jni.activity.MakeJNIActivity.initView(MakeJNIActivity.java:31)
        at com.my_project.test_jni.activity.MakeJNIActivity.onCreate(MakeJNIActivity.java:27)
        为什么我有这个错误
      • c25fe4cb884f:请问没有用到Android.mk吗?
        jarylan:@浮生若梦行 没有
      • ab42d25b4d2a:楼主棒棒哒,现在用CMake感觉很方便,但是我觉得这种也必须掌握
        jarylan:我也是这样想的 :stuck_out_tongue_winking_eye: ,还是有挺多老项目是用这种方式做的 。
      • 程序亦非猿580230:为什么我生成不了so文件
      • 在覸青春:public class JniTest {
        static {
        System.loadLibrary("jary");
        }

        public native String add(int num1, int num2);

        public native String getString();
        }

        我里面写2个方法,但是生成的.只有一个方法 这是为什么呀?
        /* DO NOT EDIT THIS FILE - it is machine generated */
        #include <jni.h>
        /* Header for class com_z_ndkxx_JniTest */

        #ifndef _Included_com_z_ndkxx_JniTest
        #define _Included_com_z_ndkxx_JniTest
        #ifdef __cplusplus
        extern "C" {
        #endif
        /*
        * Class: com_z_ndkxx_JniTest
        * Method: getString
        * Signature: ()Ljava/lang/String;
        */
        JNIEXPORT jstring JNICALL Java_com_z_ndkxx_JniTest_getString
        (JNIEnv *, jobject);

        #ifdef __cplusplus
        }
        #endif
        #endif
      • 在覸青春:看了一天,只有根据这篇操作 最后生成了想要的东西....32个赞
      • 晨起清风:apply plugin: 'com.android.application'

        android {
        compileSdkVersion 24
        buildToolsVersion "25.0.2"
        defaultConfig {
        applicationId "com.congwiny.jnitestdemo2"
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        ndk {
        moduleName "congwiny" //生成的so名字
        abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库。
        stl "stlport_static" //打开.c 的 debug , 下面第 4 点会讲到
        }
        }

        buildTypes {
        release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
        jniDebuggable true //此句不加在真机上 debug 不受影响,但是在虚拟机上不能 debug
        }
        }
        }

        dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
        })
        compile 'com.android.support:appcompat-v7:24.0.0'
        compile 'com.android.support.constraint:constraint-layout:1.0.2'
        testCompile 'junit:junit:4.12'
        }
        晨起清风:遇到个大坑:Error:Execution failed for task ':app:compileDebugNdk'.
        > com.android.ide.common.process.ProcessException: Error while executing process /Users/congwiny/Library/Android/sdk/ndk-bundle/ndk-build with arguments {NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=/Users/congwiny/Develop/Android/mydemo/JNITestDemo2/app/build/intermediates/ndk/debug/Android.mk APP_PLATFORM=android-25 NDK_OUT=/Users/congwiny/Develop/Android/mydemo/JNITestDemo2/app/build/intermediates/ndk/debug/obj NDK_LIBS_OUT=/Users/congwiny/Develop/Android/mydemo/JNITestDemo2/app/build/intermediates/ndk/debug/lib NDK_DEBUG=1 APP_STL=stlport_static APP_ABI=armeabi-v7a,armeabi,x86}
        到最后把compileSdkVersion和targetSdkVersion都改成24才行!!大家注意啊
      • Robo_G:博主有没有遇到生成的so文件很大的情况?c文件大概几百个字节,生成的so却有1M。
        jarylan:@Robo_G 请问你找到解决方法了吗。 我刚刚生成一个 demo 看了下 , 确实 so 生成就 1M 。 即使我运行 release 版本,也是这么大 。
        Robo_G: @jarylan 我是新建project的时候勾选了C++ support,用的cmake。然后make project,生成的就是1M。clean过了,也不知道是哪里的问题😂
        jarylan:不应该吧,1M 已经很大了。 一般一个 so 文件最多也就几百 k ;
        你可以先 clean 一下试试。
      • 宝杰:为什么我不会生成 .so的文件,在c文件中除了关键字是黄色外其他都是白色的,我怀疑没导入包。h成功,也没有生成ndk的文件夹,哎
        在覸青春:E:\AS_Project\NDKxx\app\src\main>javah -d jni -classpath javah -d jni -classpath E:\AS_Project\NDKxx\app\build\intermediates\classes\debug com.z.ndkxx.JniTest

        我用这一串是成功的,你看你环境ok不。。。
      • qluojieq:现在你看一下,这个文件还在这个位置吗,我的就没有ndk这个目录
        2d0800631804:@jarylan 下载了ndk,而且编译也过了,就是没有ndk这个目录,请问是什么情况呢
        jarylan:你要下载了 ndk 才会有哇 !

      本文标题:Android Studio NDK 开发与调试(生成 .so

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