Android中JNI的使用

Android中JNI的使用

       我们知道在android中进程保活,热修复,硬件接入等等都需要底层的支持,而底层代码是 C 、C++ 写的,那么在  Android  中怎么调用底层的库呢?这里就需要了解 JNI 技术。

1、什么是JNI?
      JNI是Java Native Interface的缩写,它提供了若干的 API 实现了Java和其他语言的通信(主要是 C & C++ )。从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已 编译 语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他编程语言,只要调用约定受支持就可以了。使用java与本地已编译的代码 交互 ,通常会丧失平台 可移植性 。但是,有些情况下这样做是可以接受的,甚至是必须的。例如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少要保证 本地代码 能工作在任何Java 虚拟机 环境。这个百度百科上的完整描述,下面简单点来说吧。
      JNI( Java Native Interface)意为 Java 本地调用,它允许Java代码和其他语言写的代码进行交互,简单的说,一种在Java虚拟机控制下执行代码的标准机制。

2、JNI的优缺点
优点:
 可以使用本地的代码,为java与C语言之间建立了一个桥梁
缺点:
1>、程序不再 跨平台 。要想跨平台,必须在不同的系统环境下重新编译本地语言部分。
2>、程序不再是绝对安全的,本地代码的不当使用可能导致整个程序崩溃。一个通用规则是,你应该让本地方法集中在少数几个 当中。这样就降低了JAVA和C之间的 耦合性

3、JNI的使用场景
        当你开始着手准备一个使用JNI的项目时,请确认是否还有替代方案。应用程序使用JNI会带来一些副作用。下面给出几个方案,可以避免使用JNI的时候,达到与本地代码进行交互的效果:
1、JAVA程序和本地程序使用 TCP/IP 或者 IPC 进行交互。
2、当用JAVA程序连接本地数据库时,使用 JDBC 提供的API。
3、JAVA程序可以使用分布式对象技术,如JAVA IDL API。
这些方案的共同点是,JAVA和C处于不同的线程,或者不同的机器上。这样,当本地程序崩溃时,不会影响到JAVA程序。
下面这些场合中,同一进程内JNI的使用无法避免:
1、程序当中用到了JAVA API不提供的特殊系统环境才会有的特征。而跨进程操作又不现实。
2、你可能想访问一些己有的本地库,但又不想付出跨进程调用时的代价,如效率,内存,数据传递方面。
3、JAVA程序当中的一部分代码对效率要求非常高,如算法计算,图形渲染等。
总之,只有当你必须在同一进程中调用本地代码时,再使用JNI。

4、JNI的调用过程

1)安装和下载Cygwin,下载 AndroidNDK

   2)ndk项目中JNI接口的设计

   3)使用C/C++实现本地方法

  4)JNI生成动态链接库.so文件

  5)将动态链接库复制到java工程,在java工程中调用,运行java工程即可


5、案例分析

       Android Studio 出来两年多了,网上针对 AS 开发 JNI 工程资源比较少,针对于此,我特意写下本篇博客,希望能对大家有所帮助。

配置环境

  • 下载NDK,并进行环境配置,如图:

这里讲解一下NDK:

NDK是什么?

     Android NDK(Native Development Kit )是一套工具集合,允许你用像C/C++语言那样实现应用程序的一部分。

为什么要用NDK?

    1、安全性,java是半解释型语言,很容易被反汇编后拿到源代码文件,我们可以在重要的交互功能使用C语言代替。
    2、效率,C语言比起java来说效率要高出很多。

JNI和NDK的区别?

    从工具上说,NDK其实多了一个把.so和.apk打包的工具,而JNI开发并没有打包,只是把.so文件放到文件系统的特定位置。
从编译库说
NDK开发C/C++只能能使用NDK自带的有限的头文件,而使用JNI则可以使用文件系统中带的头文件。
从编写方式说,
它们一样。

  • 项目关联NDK ,具体操作如图:

右键你的工程项目,选择 【Open Module Settings】

在 【Android NDK location】配置 NDK 的按着目录:

最后在 项目根目录 【gradle.properties】 下加上:

android.useDeprecatedNdk=true

如图:

JNI实现

新建 JNI_DEMO 项目,完成以上的配置工作。我的项目路径为:D:\Android_Study_Demos\JNI_DEMO

生成 .h 文件

新建TestJNI

public class TestJNI {

   public native String HelloWord(String str);

}

cmd命令下面,cdjava目录,输入javah -jni com.github.jni_demo.TestJNI命令,生成 .h 文件:

注意:com.github.jni_demo.TestJNI 不能 cd com , cd github……否则编译不成功。

你会发现在你的 java 路劲下生成了 com_github_jni_demo_TestJNI.h 文件:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_github_jni_demo_TestJNI */

#ifndef _Included_com_github_jni_demo_TestJNI
#define _Included_com_github_jni_demo_TestJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_github_jni_demo_TestJNI
 * Method:    HelloWord
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_github_jni_1demo_TestJNI_HelloWord
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif
然后右键  app  > New Folder  >  JNI Folder  生成jni目录如图:
然后拷贝 com_github_jni_demo_TestJNI.h到jni目录下:
生成.c文件
右键jni,生成com_github_jni_demo_TestJNI.cpp文件

拷贝以下代码到.cpp文件中:
#include <stdio.h>
#include <stdlib.h>
#include "com_github_jni_demo_TestJNI.h"
JNIEXPORT jstring JNICALL Java_com_github_jni_1demo_TestJNI_HelloWord
        (JNIEnv *env, jobject, jstring str) {
    return str;
}

build.gradle 配置 ndk

defaultConfig节点下加入如下代码:
  ndk {
            moduleName "TestJNI"
            abiFilters "armeabi", "armeabi-v7a", "x86"
        }
点击  Build  >  Make Project  如图:
编译成功后,打开 build > intermediates > ndk > debug > lib 下查看生成的 .so 文件:
Java中调用JNI:
记得把生成的.so文件拷贝到项目的libs目录下:

接着在Java中调用JNI:
package com.github.jni_demo;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

public class MainActivity extends AppCompatActivity {
    static {        // 加载动态库
        System.loadLibrary("TestJNI");
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TestJNI  testJNI=new TestJNI();
        Log.e("---------------","************"+testJNI.HelloWord("恭喜你,调用成功!"));
    }
}

这样就生成了一个属于自己的.so文件


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值