java 怎么链接ndk的库_Android中建立so库存储密钥,NDK环境搭建与jni介绍

介绍

so库介绍:Android开发中常常会见到jinLibs文件夹下的so库文件,就算用第三方的sdk也会常常看到so库,so库是一个用c/c++语言些的函数库。Android中能够用过使用jni的方式来调取so库。在某些方面so函数库可能会更高效更安全。html

JNI介绍:Java Native Interface,它是Java平台的一个特性(并非Android系统特有的)。其实主要是定义了一些JNI函数,让开发者能够经过调用这些函数实现Java代码调用C/C++的代码,C/C++的代码也能够调用Java的代码,JNI也有些本身的语法和函数。java

NDK介绍:NDK是一系列工具的集合。它提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一块儿打包成apk。如下是google官方对于NDK的介绍android

The Native Development Kit (NDK) is a set of tools that allows you to use C and C++ code with Android, and provides platform libraries you can use to manage native activities and access physical device components, such as sensors and touch input. The NDK may not be appropriate for most novice Android programmers who need to use only Java code and framework APIs to develop their apps. However, the NDK can be useful for cases in which you need to do one or more of the following:c++

Squeeze extra performance out of a device to achieve low latency or run computationally intensive applications, such as games or physics simulations.

Reuse your own or other developers’ C or C++ libraries.web

一 · 在AndroidStudio中配置NDK环境

1.下载

2cd35a3e18d14d8b88532728.html

local.properties文件中出现ndk.dir则配置成功。安全

2.配置*gradle.properties*文件,添加android.useDeprecatedNdk=true

2cd35a3e18d14d8b88532728.html

这样NDK环境就搭建ok了。ruby

二 · Java、C/C++代码编写以及so的生成与使用

1.建立对应的java类

package com.xuanguofeng.t2_ndk;

public class JniUtil {

static {

//jniutil这个参数对应着c的文件名,以及后面的配置名以及so的库名称

System.loadLibrary("jniutil");

}

//c/c++中要对应实现的方法,必须声明native

public native String getKey(String key);

}

2.对项目进行编译

2cd35a3e18d14d8b88532728.html

编译后对项目会在文件夹下出现class文件bash

2cd35a3e18d14d8b88532728.html

2.生成.h文件

打开Android Studio的Terminal也能够在对应目录的命令窗口中,切换到项目的app/src/main目录下,执行命令:app

javah -d jni -classpath 编译后的class文件的绝对路径

2cd35a3e18d14d8b88532728.html

.h文件会在app目录下的jni文件夹中,若是在不一样的目录下执行命令会在不一样的目录中生成jni文件夹

3.编写.c/.cpp文件

.c/.cpp文件的文件名要与以前在java类中定义的System.loadLibrary(“jniutil”);中的“jniutil”一致。

说明:.c文件对应的c语言,.cpp对应的是c++语言。

#include"com_xuanguofeng_t2_ndk_JniUtil.h"

#include

#include

char *RELEASE_SIGN = "330818b310f300d0660355040a0c0ce7acace4b880e8bda6e7bd9131b7f5d1bd5e607ecdc1d9a0fef8eec91b621d6071a10af23135bd3d7115865f3e5859d8f7d44b78479adeb071f48d91eb162aced5510cddc106734d152c75db1622cfdb935d7213817589d7c4a33f829c9d74ff0dd008caa9f705e30550be64fe22887373644bbb63134ec1aff680171214643cb8d1c7e5...";

char *APK_SIGN_ERROR = "签名不一致";

char *a = "a";

#... 这里能够定义更多的干扰字符

char *b = "b";

char *c = "c";

char *d = "d";

char *e = "e";

char *f = "f";

char *g = "g";

char *x = "x";

char *y = "y";

char *z = "z";

char *i1 = "1";

char *i2 = "2";

char *i3 = "3";

char *i4 = "4";

char *i5 = "5";

char *i6 = "6";

char *i7 = "7";

char *i8 = "8";

char *i9 = "9";

char *i0 = "0";

JNIEXPORT jstring JNICALL Java_com_xuanguofeng_t2_1ndk_JniUtil_getKey (JNIEnv *env, jobject obj, jstring appkey)

{

char *rtn = NULL;

jclass clsstring = env->FindClass("java/lang/String");

jstring strencode = env->NewStringUTF("utf-8");

jmethodID mid = env->GetMethodID(clsstring, "getBytes", (Ljava/lang/String;)[B");

jbyteArray barr = (jbyteArray) env->CallObjectMethod(appkey, mid, strencode);

jsize alen = env->GetArrayLength(barr);

jbyte *ba = env->GetByteArrayElements(barr, JNI_FALSE);

if (alen > 0)

{

rtn = (char *) malloc(alen + 1);

memcpy(rtn, ba, alen);

rtn[alen] = 0;

}

env->ReleaseByteArrayElements(barr, ba, 0);

if (strcmp(RELEASE_SIGN, rtn) == 0)

{

char ack[6] = "";

strcat(ack, i1);

strcat(ack, i2);

strcat(ack, i3);

strcat(ack, i4);

strcat(ack, i5);

strcat(ack, i6);

return env->NewStringUTF(ack);

} else

{

return env->NewStringUTF(APK_SIGN_ERROR);

}

}

代码说明:

RELEASE_SIGN是定一个了一个key的变量,这个key固定在so里面 是经过keystore文件生成的后面会讲解方法。缘由是若是直接单纯的返回密钥,拿到so同样不是那么安全,只有经过对应的签名文件验证经过后才会返回具体的密钥。这里返回的ack变量则是要返回给java的密钥。

说明:因为本次不怎么懂c因此只是经过查询资料简单的对密钥进行打乱拼接。读者可自行优化c算法。若有建议或者纠正欢迎留言。

4.在app目录下的build.gradle文件中添加以下代码

2cd35a3e18d14d8b88532728.html

ndk {

moduleName "jniutil"

abiFilters 'armeabi', 'x86', 'armeabi-v7a'

}

注意:此处的moduleName仍是与以前配置的 System.loadLibrary(“jniutil”); 中的jniutil一直。

5.在activity调用库中的方法。

package com.xuanguofeng.t2_ndk;

import android.content.pm.PackageInfo;

import android.content.pm.PackageManager;

import android.content.pm.Signature;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;import android.util.Log;

import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

private TextView textView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

textView= (TextView) findViewById(R.id.text);

try {

PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES);

Signature[] signs = packageInfo.signatures;

Signature sign = signs[0];

textView.setText(new JniUtil().getKey(sign.toCharsString()));

} catch (Exception e) {

e.printStackTrace();

}

}}

代码说明:

sign.toCharsString()这个方法就是获取keystore中的值来和so库中的进行比较。开发时候debug的和正式发布的keystore值是不同的因此要注意更换。

这时候点击运行项目若是签名一致就会打印密钥,若是不一致就会打印签名错误。

2cd35a3e18d14d8b88532728.html

6.so的使用

在main文件夹下建立jniLibs有的项目会放在libs中,可是须要在gradle中配置目录,实际上是同样的,复制咱们以前生成的so文件。复制对应的JniUtil类注意,包名要与以前建立的so时的包名一致。以前的jni文件下的.h和c/c++源文件以及gradle里面配置的ndk信息也都不须要了。

固然 关于ndk,jni,so的相关知识可能还有不少推荐几篇文章给你们参考。

jni讲解:http://www.jianshu.com/p/aba734d5b5cd

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值