Android studio NDK成长记录(二)ndk-build

Android studio NDK开发第二种方法 ndk-build:

  1.    首先环境配置必不可少,包括下载安装CMake,ndk-build插件,在上一篇“Android studio NDK成长记录(一)“中已经有详细介绍.
  2. 创建.c或者cpp源文件,和头文件,这一步可以先只是创建出.c和.h文件,不用急着书写.c源文件,只需搭好架子即可,书写c代码可以放到将gradle和ndk-build关联好之后,也就是第六步。(下面以c语言为例)
    第一种方式:
    在mian目录下新建jni文件夹。
    选中Android Studio的左下角Terminal面板,输入命令“cd app/src/main/java”进入java目录,执行命令“javah 包名+类名“,这个命令是调用jdk中的javah.exe程序对native方法所在的Java类生成一个对应的.h头文件。这种方式生成的.h头文件中,自动将native方法在C语言中所对应的方法名全部生成出来了。然后将生成的.h文件剪切到cpp文件夹,并将.h文件中放方法名称copy到c文件中,将参数补全即可。
    生成.h文件的命令如:“javah com.picovr.justndkbuild.nativeclass.JNI”
    第二种方式:
    在main目录新建文件夹jni,右键新建C/C++ Source File 勾选上Create an asscoiated hearder,这样就会生成一个.c文件和.h的头文件,这个.h文件不会像第一种方式那样自动生成native方法在C语言中所对应的方法名,需要自己手动去写。在学习阶段建议手动去做,更好地了解并熟悉jni的一些规则。
  3. 书写Android.mk文件,该文件名字必须为“Android.mk”,用于关联gradle和ndk-build,关联成功之后书写C代码时会有提示,否则不会有提示。Android.mk文件放在c资源文件所在module根目录中(比如app根目录)。书写好Android.mk文件后在module根目录下的build.gradle文件中配置ndk属性。Android.mk文件和build.gradle文件可配置如下:

    build.gradle :
    android {
        compileSdkVersion 25
        buildToolsVersion "25.0.0"
        defaultConfig {
            applicationId "com.picovr.justndkbuild"
            minSdkVersion 15
            targetSdkVersion 25
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    
            ndk {
                ldLibs "log"  moduleName "hello"  }
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }

    Android.mk :
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    
    #生成的so库的名字,必须跟module(如app:)下的build.gradle中配置的moduleName名字相同
    LOCAL_MODULE := hello
    
    LOCAL_LDFLAGS := -Wl,--build-id
    
    #需要在C代码中打印log到studio的控制台,第一步就需要配置该属性
    LOCAL_LDLIBS += -llog
    
    #本地 source file的地址,必须配置,Java代码才能找到源文件,并关联起来,最后面的'\'是换行,有多个文件直接按下面形式列出即可
    LOCAL_SRC_FILES := \
       E:\AndroidStudioProjects\JustNDKBuild\app\src\main\jni\hello.c \
    
    #本地 source file所在的目录
    LOCAL_C_INCLUDES += E:\AndroidStudioProjects\JustNDKBuild\app\src\main\jni
    LOCAL_C_INCLUDES += E:\AndroidStudioProjects\JustNDKBuild\app\src\main\jni
    
    include $(BUILD_SHARED_LIBRARY)
  4.     将gradle和ndk-build关联起来   ,可以手动关联,也可以自动关联,最后的结果是一样的。<1.>自动关联 : 将工程改为Android视图,右键选中module(如app),选择Link C++     Project with Gradle,下拉选项中选择ndk-build,浏览找到你的项目中的Android.mk文件,点击确定即可,studio会自动在该module下的build.gradle文件中配置好externalNativeBuild属性,最终结果与手动关联是一样的

    <2.>手动关联 : 在module下的build.gradle中按照下方的模板配置externalNativeBuild属性,该属性是指向你的Android.mk文件,让gradle编译的时候能找到该文件,按照该文件的配置进行编译
    配置好之后的build.gradle应该如下模样,注意看externalNativeBuild属性
    android {
        compileSdkVersion 25
        buildToolsVersion "25.0.0"
        defaultConfig {
            applicationId "com.picovr.justndkbuild"
            minSdkVersion 15
            targetSdkVersion 25
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    
            ndk {
                ldLibs "log"  moduleName "hello"  }
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    
        externalNativeBuild {
            ndkBuild {
                path 'Android.mk'  }
        }
    }
  5. 书写java中的native方法,创建一个类,在该类中声明一个native方法,不需要实现。
    package com.picovr.justndkbuild.nativeclass;
    
    /**
     * Created by PICO-USER Dragon on 2017/2/6.
     */
    
    public class JNI {
        public native String getString();
    }
  6. 书写c源代码
    java中的native方法对应C语言中的方法的规则在下面的代码中已经详细解释:
    copy下面的代码的时候,导包hello.h和jni.h分别copy,因为每个人的头文件名字不一样。ndk安装路径也不一样,所以jni.h所在目录不一样。
    /* Created by PICO-USER Dragon on 2017/1/17.
      导包的时候要注意
      1.你自己创建的.h文件必须要
      2.jni.h必须要,这个导包的时候,studio应该会提示,其实就是你安装ndk所在目录下的platforms目录中的任意
      一个版本中,可以在电脑中按照下面jni.h的那个路径中找来看看
     */
    
    #include "hello.h"
    #include "../../../../../../Android/SDK/ndk-bundle/platforms/android-21/arch-x86_64/usr/include/jni.h"
    #include <stdio.h>
    #include <stdlib.h>
    /**
     * 命名规则:返回值类型 + 方法名
     * 方法名:是Javanative方法的包名+类名+方法名,并且把'.'给为'_'
     *
     * JNIEXPORTJNICALL 可要可不要string Java_com_picovr_ndksupporttest_mynative_JNI_getString(JNIEnv *env, jobject jobj)也行
     *
     * jstring 是返回值对应java中的String
     * JNIEnv *env 必须参数,在C中必须要用到这个参数去调用方法
     * jobject jobj 必须参数 不一定用到
     */
    JNIEXPORT jstring JNICALL
    Java_com_picovr_ndksupporttest_mynative_JNI_getString(JNIEnv *env, jobject jobj) {
    
        //jstring     (*NewStringUTF)(JNIEnv*, const char*);其实是在调用ndk-build中的jni.h中的方法
        return (*env)->NewStringUTF(env, "The first jinDemo for Dragon !");
    
    }
  7. 加载动态链接库,调用c代码
    在native方法所在类中增加静态代码块,加载动态链接库
    package com.picovr.justndkbuild.nativeclass;
    
    /**
     * Created by PICO-USER Dragon on 2017/2/6.
     */
    
    public class JNI {
    
        // Used to load the 'hello' library on application startup. 
        static {
            //"hello"是so库的名字,也就是CMakeLists.txt文件中add_library()属性中的第一个参数 
            System.loadLibrary("hello");
        }
    
        public native String getString();
    }
  8. 调用native方法,看看是否成功!
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            String string = new JNI().getString();
            Log.i("MainActivity", "onCreate string :" + string);
        }
    }

 

转载于:https://my.oschina.net/u/2337595/blog/832275

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值