JNI入门学习笔记

来源:互联网 发布:自动阅读小说的软件 编辑:程序博客网 时间:2024/06/05 03:20

最近因公司业务需要,将一部分逻辑代码从java移入JNI中。本着现学现用的精神,终于在deadline前完成交付。现记下此文作为我学习JNI过程中的点滴。

废话不多说,直接开干

搭建环境

我用的开发工具是MAC,AS。关于安装NDK网上有很多方法,我用的是最懒的方法,如图
这里写图片描述

因为我这已经下载好了NDK,所以没有显示。
未下载NDK时会提示,是否下载,我是直接点击 load ndk让AS帮我下载好的。

友情提示:此法下载需要科学上网

编写java文件

我新建了两个java文件,JNIFragment用于调用底层方法并显示处理结果,JNICalc 声明了一个简单的计算方法。
JNIFragment.java

public class JNIFragment extends BaseFragment {    @Override    public String getTAG() {        return JNIFragment.class.getSimpleName();    }    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        LinearLayout linearLayout = new LinearLayout(getActivity());        linearLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));        linearLayout.setOrientation(LinearLayout.VERTICAL);        Button button = new Button(getActivity());        button.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));        button.setText("32+44=?");        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                LogDetails.i(JNICalc.calc(32,44));                showToastShort(JNICalc.calc(32,44)+"");            }        });        linearLayout.addView(button);        return linearLayout;    }}

JNICalc.java

public class JNICalc {    public static native int calc(int a,int b);    static {        System.loadLibrary("jniDemo"); // 标记1    }}

生成.h文件

依次点击 Build->clean project->rebuild project运行结束后, 找到class文件所在路径app/build/intermediates/classes/tt/blue/com/bruce/demo/studydata/fragments/jnidemo/JNICalc.class

打开终端输入命令

javah -jni 包名JNICalc

如果包名不正确就会报错

Exception in thread “main” java.lang.IllegalArgumentException: Not a valid class name

或者

error occurred during initialization of VM java.lang.Error: Properties init: Could not determine current working directory. at java.lang.System.initProperties(Native Method) at java.lang.System.initializeSystemClass(System.java:1163)

或者

javah -jni com.bruce.demo.studydata.fragments.jnidemo.JNICalc 错误: 找不到 com.bruce.demo.studydata.fragments.jnidemo.JNICalc 的类文件。

对于我的demo中的正确的输入方法如下
进入JNICalc.class文件所在路径的根目录

cd app/build/intermediates/classes/tt/blue/

编译生成.h文件,文件路径app/build/intermediates/classes/tt/blue/

javah -jni com.bruce.demo.studydata.fragments.jnidemo.JNICalc

编写native文件

在main目录下新建jni文件夹,并将上面生成的.h文件copy到这个文件夹下,新建 cppcalc.cpp文件

#include <com_bruce_demo_studydata_fragments_jnidemo_JNICalc.h>JNIEXPORT jint JNICALL Java_com_bruce_demo_studydata_fragments_jnidemo_JNICalc_calc  (JNIEnv *, jclass, jint a, jint b){   return a+b;  }

编写.mk

编写Android.mk文件

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE    := jniDemo  LOCAL_SRC_FILES := cppcalc.cppinclude $(BUILD_SHARED_LIBRARY)

这里需要注意的地方有两处:

LOCAL_MODULE 填写的jniDemo必须与 标记1相同
LOCAL_SRC_FILES 填写的 cppcalc.cpp就是上面的cpp文件名称必须 一 一对应

生成.so

输入 ndk-build 生成.so
这里也要注意
可能输入完这条命令会出现以下错误
>

1.

Android NDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it. /Users/XXX/Library/Android/sdk/ndk-bundle/build/core/build-local.mk:151: Android NDK: Aborting . Stop.


2.

Android NDK: Your APP_BUILD_SCRIPT points to an unknown file: app/src/jni/Android.mk/jni/Android.mk
/Users/XXX/Library/Android/sdk/ndk-bundle/build/core/add-application.mk:198: * Android NDK: Aborting… . Stop.

解决办法是进入到当前工程所在目录,build时指明源文件所在路径的父路径

cd asstudydemondk-build NDK_PROJECT_PATH=app/src/main/

这样就生成了若干个.so包

在工程上使用.so

生成的.so包考入main包下的jniLibs中或者lib中都可以,打包安装,测试。此过程中可能会出现

NDK integration is deprecated in the current plugin. Consider trying the new experimental plugin.For details, see http://tools.android.com/tech-docs/new-build-system/gradle-experimental. Set “Android.useDeprecatedNdk=true” in gradle.properties to continue using the current NDK integration.

的错误,则需要修改 gradle.properties文件增加 android.useDeprecatedNdk=true 即可

demo
参考资料:
NDK integration is deprecated解决方法
https://developer.android.com/ndk/guides/android_mk.html

0 0