Android开发之JNI基础

在Android的开发中,有时候我们需要和底层的C代码进行交互,这时我们就需要使用JNI技术了,可能我们不需要去直接编写C代码,但是我们能理解和编写简单的使用JNI也是对我们的开发有很大帮着,例如,有时候我们需要使用一些对象云存储服务的时候,它给我们带来便捷的同时也带了一些危险,如果我们直接把密钥写在Java层,很容易被人家反编译后知道,然后访问我们的云存储,为了降低这种风险,我们可以使用JNI将密钥放在C层,C层的代码是二进制的,这样就可以起到一定的保护作用。

一、JNI开发环境配置

这里我们首先需要下载NDK开发工具,我所使用的是r9d版本的,下载地址为http://tools.android-studio.org/

下载完成后,直接解压放在我们的电脑中,然后配置环境变量,如果我们使用Android Studio进行开发这一步也可以省略。在Android Studio中,我们可以local.properties文件中配置如下:

    ndk.dir=F\:\\Java\\sdk\\ndk-bundle
    sdk.dir=F\:\\Java\\sdk

这里需要根据自己的实际情况进行配置,然后我们就可以进行JNI开发了。

二、实现简单的函数

这里我们就简单的使用两个方法,通过C层返回一个字符串和在Java层传入连个参数,C层返回它们的和。

  1. 我们先在Java层创建一个类,然后在这个类中定义两个Native方法:

    public class FirstJni {
    
    private static String libName="firstjni";
    
    static {
        System.loadLibrary(libName);
    }
    
    public static native String getStringFromNative();
    
    public static native int getIntFromNative(int a,int b);
    }

    2.然后我们Make一下我们的工程,在AS中的快捷键是Ctrll+F9,我们就可以在build目录下得到一个class文件。
    3.使用javah指令生成头文件,打开AS中自带的控制台,进入main目录下,运行如下代码:

javah -d jni -classpath F:/Java/sdk/platforms/android-16/android.jar:../../build/intermediates/classes/debug dave.com.jnidevelope.FirstJni

这里值得注意的地方是,classpath后面的内容是sdk目录下android.jar的路径,后面紧跟一个冒号,然后就是刚才文件的class文件的路径。
4.这是,我们就发现在main目录下多了一个jni文件夹,目录结构如下:
这里写图片描述
5.编写C层的代码实现,具体代码如下:

#include "dave_com_jnidevelope_FirstJni.h"
#include <jni.h>
#include <android/log.h>

JNIEXPORT jstring JNICALL Java_dave_com_jnidevelope_FirstJni_getStringFromNative
  (JNIEnv *env,jobject obj){
    return (*env)->NewStringUTF(env,"i am come from jni native");
  }

JNIEXPORT jint JNICALL Java_dave_com_jnidevelope_FirstJni_getIntFromNative
  (JNIEnv *env,jobject obj,jint a,jint b){
    return a+b;
  }

其中第一个方法就是C层生成一个string的方法,该方法的声明包含在jni.h头文件中,我们可以在NDK开发工具中的目录下找到:

F:\Java\sdk\ndk-bundle\platforms\android-9\arch-arm\usr\include

至此,我们就差最后一步了,我们需要生成so库文件,在eclipse中,我们需要在jni的目录下创建一个Android.mk文件,内容大致如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := firstjni
LOCAL_LDFLAGS := -Wl,--build-id
LOCAL_LDLIBS := \
    -llog \
    -lz \
    -lm \

LOCAL_SRC_FILES := \
    H:\Android\JNIDevelope\app\src\main\jni\main.c \

LOCAL_C_INCLUDES += H:\Android\JNIDevelope\app\src\main\jni
LOCAL_C_INCLUDES += H:\Android\JNIDevelope\app\src\debug\jni

include $(BUILD_SHARED_LIBRARY)

但是在AS中我们不需要这么麻烦,只需要在Module下的gradle文件中配置如下就行了:
这里写图片描述
在这个文件中,如果我们不希望c代码放在jni目录下,我们还可以配置自定义的路径,在android下配置

        sourceSets {
            main {
                jniLibs.srcDirs 'src/main/jniLibs'
            }
        }

至此,我们重新Make下工程,我们就可以生成so库文件了,那么它在什么地方了:
这里写图片描述

H:\Android\JNIDevelope\app\build\intermediates\ndk

最后,我们就可以在我们的代码中使用者两个方法了,使用的时候我们需要加载进来:

    static {
        System.loadLibrary(libName);
    }
    //libName就是我们gradle里面配置的moduleName

使用方法如下:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView text = (TextView) findViewById(R.id.text);
        int fromNative = FirstJni.getIntFromNative(3, 5);
        String stringFromNative = FirstJni.getStringFromNative();
        text.setText(stringFromNative+fromNative);
    }
}

以上就是JNI开发中的一些基础知识,文中不足之处,希望大家指正!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值