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 /* Header for class com_github_jni_demo_TestJNI */#ifndef _Included_com_github_jni_demo_TestJNI#define _Included_com_github_jni_demo_TestJNI#ifdef __cplusplusextern "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 #include #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. android:shape的使用 (android用xml文件生成图像控件)
  2. android中的后退键——onBackPressed()的使用
  3. android设置背景图片透明
  4. 安卓隐藏标题栏状态栏 ,实现全屏效果
  5. Android(安卓)Activity 常用功能设置(全屏、横竖屏等)
  6. Android(安卓)SDK各版本源码
  7. android定位个人当前位置
  8. android 列表 数据显示总结
  9. ListActivity setContentView 错误

随机推荐

  1. ECLIPSE android 布局页面文件出错故障排
  2. android实现瀑布流加载图片
  3. Android内置颜色及其它颜色RGB对照表
  4. cocos2dx的学习
  5. Android程序开发初级教程(三)
  6. android adb 获取所有app 的uid
  7. Android(安卓)root的两种方法-udev漏洞和
  8. 解决Android(安卓)Logcat不打印信息
  9. android Preference视图的使用
  10. HP TouchPad & Android