Android studio之Jni/ndk入门

android studio使用jni的方法很简单,但是在使用的过程中会出现很多的问题,查阅了很多教程,今天做个总结:

1、不要在继承AppCompatActivity的类中声明native方法,另写一个类,如下声明加载so的静态代码块,以及声明一个native方法,如下所示:

package com.chensd.jnitest;

/**
 * Created by chensd on 2016/11/23.
 */
public class JniTest {

    public native String getStringFromNative();

    static {
        System.loadLibrary("JniTest");
    }
}
2、如上操作后,native方法会是红色的,不要在意这个!下文再解决。接下来在main\src\java下的acitivty编写简单的实例代码:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        JniTest jniTest = new JniTest();

        TextView textview = (TextView) findViewById(R.id.textview);
        textview.setText(jniTest.getStringFromNative());

    }
}
3、编译生成class文件,两种方法:

a)直接利用Build->Make Project

b)打开Terminal  cd到我们的JniTest.java文件下,执行 javac JniTest.java

编译后生成的文件在../app/build/intermediates/classes/debug/com/chensd/jintest

4、利用javah命令生成.h头文件:

打开Terminal,定位到项目的java文件下,执行javah命令

E:\android_csd\JniTest\app\src\main\java>javah -d ../jni com.chensd.jnitest.JniTest
之后会在java的同级目录下生成一个jni目录,该目录下会有一个.h的文件

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_chensd_jnitest_JniTest */

#ifndef _Included_com_chensd_jnitest_JniTest
#define _Included_com_chensd_jnitest_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_chensd_jnitest_JniTest
 * Method:    getStringFromNative
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_chensd_jnitest_JniTest_getStringFromNative
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
5、在jni目录下新建一个main.c的文件,copy 该.h文件内容,并且实现里面的主题方法返回一个简单的字符串:

#include <jni.h>
/* Header for class com_chensd_jnitest_JniTest */

#ifndef _Included_com_chensd_jnitest_JniTest
#define _Included_com_chensd_jnitest_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_chensd_jnitest_JniTest
 * Method:    getStringFromNative
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_chensd_jnitest_JniTest_getStringFromNative
  (JNIEnv * env, jobject jobj){
        return (*env)->NewStringUTF(env,"come_from_jnitest");//返回一个简单的字符串
  };

#ifdef __cplusplus
}
#endif
#endif
另外再新建一个空的util.c的文件,这样android才能顺利编译so。

6、配置下NDK,可以去开发者工具集网站下载压缩包也可以直接在android studio里面下载,ctrl+shift+a,键入system settings,定位到android sdk->sdk tools 找到NDK并且下载安装!

a)打开gradle.properties文件末尾加上一句话:

android.useDeprecatedNdk=true
b)打开local.properties检查是否配置NDK路劲:

sdk.dir=D\:\\AndroidSDK\\android-sdk-windows
ndk.dir=D\:\\AndroidNDK\\android-ndk-r13b

c)配置下app module下build.gradle配置下NDK:

defaultConfig {
        applicationId "com.chensd.jnitest"
        minSdkVersion 14
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"

        ndk {
            moduleName "JniTest" //必须与静态代码块中的相同
            ldLibs "log", "z", "m"
            abiFilters "armeabi", "armeabi-v7a", "x86"
        }
    }
7、生成so文件,点击build->rebuild,so文件生成路径在,..\app\build\intermediates\ndk\debug\lib

接下来按照之前在MianActivity中的代码示例运行下,就成功了!




经过如上的折腾,简单的jni使用已经可以了,但是有一个问题:在main.c中我们导入.h文件会抱红,编写C代码不会联想等等的问题,为了解决这些问题,正常的可以开发NDK需要进行如下配置:
1、修改工程目录下的的build.gradle的classpath:
classpath 'com.android.tools.build:gradle-experimental:0.7.0'
2、修改app module下build.gradle文件
apply plugin: 'com.android.model.application' //这里变化了
model {
    android {
        compileSdkVersion = 23
        buildToolsVersion = "23.0.0"
        defaultConfig.with {
            applicationId = "com.chensd.ndkdeveloputil"
            minSdkVersion.apiLevel = 14
            targetSdkVersion.apiLevel = 23
        }
        tasks.withType(JavaCompile){
            //指定编译JDK版本
            sourceCompatibility=JavaVersion.VERSION_1_7
            targetCompatibility=JavaVersion.VERSION_1_7
        }
    }
/*    * native build settings    */
    android.ndk {
        moduleName = "jnitest" //必须与JniTest类中的一致
//        cppFlags.add("-fno-rtti")
//        cppFlags.add("-fno-exceptions")
//        ldLibs.addAll(["android", "log"])
//        stl      = "system"
    }
    android.buildTypes {
        release {
            minifyEnabled = false
            proguardFiles.add(file('proguard-rules.txt'))
        }
    }
    android.productFlavors {
// for detailed abiFilter descriptions, refer to "Supported ABIs" @
// https://developer.android.com/ndk/guides/abis.html#sa
        create("arm") {
            ndk.abiFilters.add("armeabi")
        }
        create("arm7") {
            ndk.abiFilters.add("armeabi-v7a")
        }
        create("arm8") {
            ndk.abiFilters.add("arm64-v8a")
        }
        create("x86") {
            ndk.abiFilters.add("x86")
        }
        create("x86-64") {
            ndk.abiFilters.add("x86_64")
        }
        create("mips") {
            ndk.abiFilters.add("mips")
        }
        create("mips-64") {
            ndk.abiFilters.add("mips64")
        }
        // To include all cpu architectures, leaves abiFilters empty
        create("all")
    }
}
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
}
也可以替换成如下:
apply plugin: 'com.android.model.application' //这里变化了
model {
    android {
        compileSdkVersion = 23
        buildToolsVersion = "23.0.0"
        defaultConfig.with {
            applicationId = "com.chensd.ndkdeveloputil"
            minSdkVersion.apiLevel = 14
            targetSdkVersion.apiLevel = 23
        }
        tasks.withType(JavaCompile){
            //指定编译JDK版本
            sourceCompatibility=JavaVersion.VERSION_1_7
            targetCompatibility=JavaVersion.VERSION_1_7
        }
    }
/*    * native build settings    */
    android.ndk {
        moduleName = "jnitest" //必须与JniTest类中的一致
//        ldLibs.addAll(["android", "log"])
        abiFilters.add("armeabi")
        abiFilters.add("armeabi-v7a")
        abiFilters.add("x86")
    }
    android.buildTypes {
        release {
            minifyEnabled = false
            proguardFiles.add(file('proguard-rules.txt'))
        }
    }

}
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
}
这样配置android.productFlavors后,rebuild后会在app->build->intermediates->transforms->mergeJniLibs下生成so库。

NDK正常编译demo:
https://github.com/chenshandong/NDKDevelopUtil


     








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值