Androidstudio中JNI开发初探

前言

我觉得这个大神讲的很好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






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值