android v8 jni开发,NDK开发 - JNI开发流程

JNI是Java和C/C++建立连接的桥梁,开发者可以将关键的加密算法通过用C/C++实现以提高被反编译的难度,保护APK的数据安全。又或者通过C/C++获取一些手机数据,以此来绕过类似Xposed这类作弊工具,提高数据的准确性。

源码地址:https://github.com/gnaix92/as-ndk

在上一篇搭建的环境下,就可以进行NDK的开发。NDK开发主要分为一下几个步骤:

java层入口代码编写

java代码编译

C/C++头文件生成

C/C++代码编写

运行编译SO

java层代码编写

新建一个NativeMethod的Class,java层代码主要负责两件事:

Load native library(SO文件)

Load操作很简单,其中包名为build.gradle中定义的ndk名,代码如下:

android.ndk {

moduleName = "native" //设置库(so)文件名称

// CFlags.add("-DCUSTOM_DEFINE")

ldLibs.addAll(["log", "android", "EGL", "GLESv1_CM"])

// ldFlags.add("-L/custom/lib/path")

stl = "stlport_static"

}

static{

System.loadLibrary("native");

}

定义接口名

JNI的接口名以native字符修饰,并且不需要实现。

package com.example.gnaix.ndk;

/**

* 名称: NativeMethod

* 描述:

*

* @author xiangqing.xue

* @date 16/3/10

*/

public class NativeMethod {

static{

System.loadLibrary("native");

}

/**

* 基础类型

* @param i

* @return

*/

public static native int getInt(int i);

/**

* string

* @param str

* @return

*/

public static native String getString(String str);

/**

* array

* @param data

* @return

*/

public static native byte[] getByteArray(Byte[] data);

/**

* 调用java对象

* @param name

* @param age

*/

public static native void invokeJobject(String name, int age);

/**

* 调用java静态方法

*/

public static native void invokeStaticFieldAndMethod();

/**

* 获取结构体

* @return

*/

public static native Person[] getPersons();

}

到这里java层的活就干完了。

java代码编译

在生成C/C++的头文件前需要把上面写的class编译成.class文件。Android Studio中编译很简单点一下右上角的blog...%20style=按钮就可以了。生成的class文件在app/build/intermediates/calsses/all/debug/xx.xx.xx/xx.class。

C/C++头文件生成

JNI开发对C/C++的头文件有命名的格式要求,所以我们可以使用jdk提供的javah命令生成规定的C/C++头文件。为了方便可以先切换到app/src/main目录下。

cd app/src/main

再执行javah命令。(根据实际替换需要生成的class文件)

javah -d jni -classpath ../../build/intermediates/classes/all/debug com.example.gnaix.ndk.NativeMethod

参数说明:

classpath:类搜索路径

d:将生成的头文件放到当前的 jni 目录下

o: 指定生成的头文件名称,默认以类全路径名生成(包名+类名.h)

执行完会发现在main目录下生成了一个jni目录,里面有个com_example_gnaix_ndk_NativeMethod.h的头文件。里面有生成好的头文件。

/* DO NOT EDIT THIS FILE - it is machine generated */

#include

/* Header for class com_example_gnaix_ndk_NativeMethod */

#ifndef _Included_com_example_gnaix_ndk_NativeMethod

#define _Included_com_example_gnaix_ndk_NativeMethod

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: com_example_gnaix_ndk_NativeMethod

* Method: getInt

* Signature: (I)I

*/

JNIEXPORT jint JNICALL Java_com_example_gnaix_ndk_NativeMethod_getInt

(JNIEnv *, jclass, jint);

/*

* Class: com_example_gnaix_ndk_NativeMethod

* Method: getString

* Signature: (Ljava/lang/String;)Ljava/lang/String;

*/

JNIEXPORT jstring JNICALL Java_com_example_gnaix_ndk_NativeMethod_getString

(JNIEnv *, jclass, jstring);

/*

* Class: com_example_gnaix_ndk_NativeMethod

* Method: getByteArray

* Signature: ([Ljava/lang/Byte;)[B

*/

JNIEXPORT jbyteArray JNICALL Java_com_example_gnaix_ndk_NativeMethod_getByteArray

(JNIEnv *, jclass, jobjectArray);

/*

* Class: com_example_gnaix_ndk_NativeMethod

* Method: invokeJobject

* Signature: (Ljava/lang/String;I)V

*/

JNIEXPORT void JNICALL Java_com_example_gnaix_ndk_NativeMethod_invokeJobject

(JNIEnv *, jclass, jstring, jint);

/*

* Class: com_example_gnaix_ndk_NativeMethod

* Method: invokeStaticFieldAndMethod

* Signature: ()V

*/

JNIEXPORT void JNICALL Java_com_example_gnaix_ndk_NativeMethod_invokeStaticFieldAndMethod

(JNIEnv *, jclass);

/*

* Class: com_example_gnaix_ndk_NativeMethod

* Method: getPersons

* Signature: ()[Lcom/example/gnaix/ndk/Person;

*/

JNIEXPORT jobjectArray JNICALL Java_com_example_gnaix_ndk_NativeMethod_getPersons

(JNIEnv *, jclass);

#ifdef __cplusplus

}

#endif

#endif

C/C++代码编写

生成头文件后就可以写具体的C++的实现代码,这里只写了一小段实现代码,具体的调用开发细节下一篇再说。 实现了getInt方法,获取了android的serialno,并用log打印出来。

//

// Created by 薛祥清 on 16/3/10.

//

#include "com_example_gnaix_ndk_NativeMethod.h"

#include

#include

using namespace std;

#define ENABLE_DEBUG 1

#if ENABLE_DEBUG

#define TAG "NDK_NATIVE"

#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG,TAG, fmt, ##args)

#define DEBUG_PRINT(format, args...) \

LOGD(format, ##args)

#else

#define DEBUG_PRINT(format, args...)

#endif

JNIEXPORT jint JNICALL Java_com_example_gnaix_ndk_NativeMethod_getInt

(JNIEnv *env, jclass object, jint num)

{

int len;

char buf[1024];

__system_property_get("ro.serialno", buf);

LOGD("name : %s", buf);

return num;

}

运行编译SO

经过上面的步骤,已经可以编译了,在NDK开发中除了自己apk需要,更多时候是作为第三方包提供给客户使用。Android Studio也为我们打包好了,可以在module目录下找到。

1460000006770037?w=302&h=497

PS:

这里需要注意debug模式编译会产生gdb.steup gdbserver这两个是gdb调试工具,在正式发布必须要用release模式编译。

旧版本android-ndk-r9d只能编译armeabi armeabi-v7a mips x86四种cpu架构的,现在大多数手机已经是64位架构了,旧版本已经不能支持所有手机了。所以在android-ndk-r10e中增加了arm64-v8a mips64 x86_64三种架构。

目前最新的NDK版本为android-ndk-r11b

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值