Android Studio JNI 流程

"Android Studio 2.2" 后编译环境发生了变化,欲知详情,请移步:

Android JNI for "Android Studio 2.2 or higher"」     更新于2016-11-05


-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

1. 在Android code中,加载so库,添加native方法

package com.stone.jni;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

/**
 * author : stone
 * email  : aa86799@163.com
 * time   : 16/2/16 23 45
 */
public class MainActivity extends Activity {


    static {
        System.loadLibrary("stonelib_test");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        TextView tv = new TextView(this);
        setContentView(tv);

//        tv.setText(hello("admin"));
        tv.setText(hello("中华小子"));

    }

    public native String hello(String username);
}


2. 利用javah命令,生成当前native方法所在类的对应的 .h 头文件

先build一下工程,生成源文件对应的.class文件。通过菜单栏中的Build>Make Project 或 Make Module 选项

在 <project>/<module>/build/intermediates/classes/debug/ 目录下生成相应的.class文件

$ cd <project>/<module>/src/main   

$ javah -d jni -classpath <android.jar-path>:<project>/<module>/build/intermediates/classes/debug/ com.stone.jni.MainActivity

会在studio中的module/src/main 下生成一个jni目录,并生成一个.h头文件

生成的.h文件:

#ifndef _Included_com_stone_jni_MainActivity
#define _Included_com_stone_jni_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_stone_jni_MainActivity
 * Method:    hello
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT jstring JNICALL Java_com_stone_jni_MainActivity_hello
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

如果要编译生成的类MainActivity 引用了其它lib库,那么在-classpath 选项后也要加上该lib的路径 , 以 冒号(:)间隔



在extern "C" { … } 中 按C语言进入编译,而不是C++

在{}之外就是按C++ 编译了

note:

JNIEXPORT、JNICALL 为jni关键字 ,表示jni调用将调用后面的方法
Java_com_stone_jni_MainActivity_hell  方法名,以Java_ 开头,后跟完全限定类名和方法名
关于方法的参数:

第一个是 JNIEnv *类型。第二个jobject类型表示该方法是一个实例方法;

若方法本身是一个static修饰的静态方法,那么第二个参数会是jclass类型。

再之后的才是java方法中的参数对应的在jni中的数据类型
JNIEXPORT jstring JNICALL Java_com_stone_jni_MainActivity_hell (JNIEnv *, jobject, jstring);


3. 编写.c 或 .cpp/.cc 文件 (前者对应C语言,后者对应C++语言)

这里在C中调用String类的相关方法;需要通过 命令拿到java类的 所有方法签名
$ javap -s java.lang.String


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

#ifndef _Included_com_stone_jni_MainActivity
#define _Included_com_stone_jni_MainActivity
#ifdef __cplusplus
extern "C" {
#endif

/*
 * Class:     com_stone_jni_MainActivity
 * Method:    hello
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT jstring JNICALL Java_com_stone_jni_MainActivity_hello
        (JNIEnv *env, jobject obj, jstring jstr)
{
    jstring hel = (*env)->NewStringUTF(env, "hello,");

    jclass cls = (*env)->FindClass(env, "java/lang/String");
    jmethodID initId = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V");
    jobject object = (*env)->NewObject(env, cls, initId, hel);

    jmethodID concatM = (*env)->GetMethodID(env, cls, "concat", "(Ljava/lang/String;)Ljava/lang/String;");
    jstring ss = (*env)->CallObjectMethod(env, object, concatM, jstr);

    return ss;
}

#ifdef __cplusplus
}
#endif
#endif

4. 在build.gradle中配置NDK

> 在local.properties文件中
  添加 ndk.dir=ndk-path    //指定ndk路径

> 修改module下的build.gradle配置(关于Studio2.2后的配置,请点击本文开头的链接)

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        applicationId "com.stone.jni"
        minSdkVersion 8
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
        ndk {
            moduleName "stonelib_test"  //库的名字
            ldLibs "log", "z", "m"  //附加系统库
            abiFilters "armeabi", "armeabi-v7a", "x86", "mips"  //cpu架构
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
}

然后运行工程,生成的so文件目录<Project>/app/build/intermediates/ndk/

mk文件,也会自动生成于该目录下



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值