您的位置:首页 > 移动开发 > Android开发

Androidstudio中JNI开发初探

2016-10-27 16:54 513 查看
前言

我觉得这个大神讲的很好jni的用途

NDK全称是Native Development Kit,NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。NDK集成了交叉编译器(交叉编译器需要UNIX或LINUX系统环境),并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。

为什么使用NDK?

1.)代码的保护。由于apk的java层代码很容易被反编译,而C/C++库反汇难度较大。

2.)可以方便地使用现存的开源库。大部分现存的开源库都是用C/C++代码编写的。

3.)提高程序的执行效率。将要求高性能的应用逻辑使用C开发,从而提高应用程序的执行效率。

4.)便于移植。用C/C++写得库可以方便在其他的嵌入式平台上再次使用。

什么是JNI?

JNI全称是Java Native Interface(Java本地接口)单词首字母的缩写,本地接口就是指用C和C++开发的接口。由于JNI是JVM规范中的一部份,因此可以将我们写的JNI程序在任何实现了JNI规范的Java虚拟机中运行。同时,这个特性使我们可以复用以前用C/C++写的大量代码。

为什么使用JNI?

JNI的目的是使java方法能够调用c实现的一些函数。

安卓中的so文件是什么?

Android中用到的so文件是一个c++的函数库。在android的JNI中,要先将相应的C语言打包成so库,然后导入到lib文件夹中供java调用。

NDK环境安装

请参照我上一篇博客,照着做就可以了
在Android Studio中NDK环境配置

JNI的开发流程

JNI开发流程主要分为以下6步:

1、编写声明了native方法的Java类

2、将Java源代码编译成class字节码文件

3、用javah -jni命令生成.h头文件(javah是jdk自带的一个命令,-jni参数表示将class中用native声明的函数生成jni规则的函数)

4、用本地代码实现.h头文件中的函数

5、将本地代码编译成动态库(windows:*.dll,linux/unix:*.so,mac os x:*.jnilib)

6、拷贝动态库至 java.library.path 本地库搜索目录下,并运行Java程序

JNI初探

1.新建工程,编写xml布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/activity_main"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="jnidemo.demo.com.jnidemo.MainActivity">

<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""/>
</RelativeLayout>

2.在Activity上的代码如下:

public class MainActivity extends AppCompatActivity {

//加载动态so库,这个名字跟build.gradle中配置moduleName的名字一样
static {
System.loadLibrary("jnidemo");
}

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

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

//声明一个本地方法,用native关键字修饰,这是jni调用的方法
public native String getStringFromNative();
}

3.生成.h头文件,在Androidstudio上的Terminal上输入下面命令:

cd app/src/main/java

javah -jni jnidemo.demo.com.jnidemo.MainActivity (javah -jni 包名+类名)

就会在app/src/main/java目录下自动生成一个.h文件,类似这样的文件:

jnidemo_demo_com_jnidemo_MainActivity.h

生成的.h文件内容:

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

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

#ifdef __cplusplus
}
#endif
#endif

其实这里都是自动生成的,最关键的就是这一句了
JNIEXPORT jstring JNICALL Java_jnidemo_demo_com_jnidemo_MainActivity_getStringFromNative
(JNIEnv *, jobject);


那个名称:Java_包名_类名_方法名
4.然后新建jni文件夹,并拷贝上面生成的.h文件到jni目录

选择File->New->Folder->JNI Folder



在弹出的对话框中要选择Change Folder Location,它会自动给你一个Folder名字src/main/jni/,然后finish就生成了





5.然后在jni文件夹下新建一个.c文件,文件名随意,把上面自动生成的.h文件的东西复制过去进行修改,如下

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

#ifndef _Included_jnidemo_demo_com_jnidemo_MainActivity
#define _Included_jnidemo_demo_com_jnidemo_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     jnidemo_demo_com_jnidemo_MainActivity
* Method:    getStringFromNative
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_jnidemo_demo_com_jnidemo_MainActivity_getStringFromNative
(JNIEnv *env, jobject jobject1){
char *str = "Hello JNI!";
return (*env)->NewStringUTF(env, str);

}

#ifdef __cplusplus
}
#endif
#endif

6.生成SO库

完成以上步骤,在Androidstudio工具栏上点击Make Project就可以了,如果不行就重新clean Project一下,再Rebuild Project,应该就可以了



然后可以在项目的app\build\intermediates\ndk\debug\lib路径下看到编译成功对应的so库了:



7.假如是给别人用你的SO库,就可以直接在main目录先新建一个jniLIB(app/src/main/jniLIB),并将生成好的SO文件拷贝到该目录下就可以用了



8.运行一下项目就可以看到刚才那个.c文件中的数据了 “Hello JNI!"



**就这样,第一个jni项目就完成了,nice
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jni android studio ndk