使用互联网有很多javah命令生成一个头文件来完成JNI写,但事实上ADT集成NDK后。点点鼠标就可以了,网上的介绍是非常小懒的方法,在这里,我们主要谈论的懒惰JNI发展。

为ADT组态NDK。请个人google或视图Android developer,不多做描述在这里。

1. 新建一个Androidproject,我这边取名为JNI_Learn,一键生成后代码片段例如以下:

public class JNI extends ActionBarActivity {static{System.loadLibrary("JNI_Learn");}public native int plus(int x, int y);    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_jni);                if (savedInstanceState == null) {            getSupportFragmentManager().beginTransaction()                    .add(R.id.container, new PlaceholderFragment())                    .commit();        }                Log.d("JNITest", "3+5=" + plus(3, 5));            }
高亮部分是我自己加入部分。简单解释一下。

loadLibrary的话,里面的名字稍后我会再标注一下,这边主要是native层生成的so库的名字,须要去掉lib前缀和.so后缀。

声明native方法要在訪问权限之后,其它声明之前,加一个native标记此方法实如今native层。

使用plus方法与正常使用无异。

2. 之后就是懒人操作了,在project上右击鼠标。选择Android Tools->Add Native Support...


之后查看project里面有两个文件


第一个是JNI_Learn.cpp,这个稍后详述。第二个是Android.mk。在Android编译中。都会寻找文件夹下是否存在Android.mk,然后依据这个文件进行编译。里面编写了详细的编译规则,打开文件后。内容例如以下:

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_LDLIBS := -llogLOCAL_MODULE    := JNI_LearnLOCAL_SRC_FILES := JNI_Learn.cppinclude $(BUILD_SHARED_LIBRARY)
除加红部分外,其它都为自己主动生成,加红部分是我加入为了使用native的log方法
当中LOCAL_PATH表示编译源文件的路径,LOCAL_LDLIBS表示编译模块时须要附加的连接器选项,LOCAL_MODULE表示终于编译出来模块的名称。LOCAL_SRC_FILES表示须要编译的源文件,include $(BUILD_SHARED_LIBRARY)表示终于编译成一个共享库文件。


3. 以下详细加入native层对plus方法的实现代码

#include <jni.h>#include <android/log.h>#define LOG_TAG "JNITest"//log func//int __android_log_print(int prio, const char *tag,  const char *fmt, ...)#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)extern "C"JNIEXPORT int Java_com_example_jni_1</span>learn_JNI_plus");return x + y;}

使用了Android log将log打印到了logcat一样。想了解的能够自行查阅相关知识,这边没太大关系。这个也是在Android.mk中为什么须要添加LOCAL_LDLIBS原因。

extern “C”是必需要加的,由于C++和C编译后的导出函数原型不同,java仅仅能call C类型的,所以需要将C++转化为C类型的。添加extern "C"声明。

JNIEXPORT声明他是一个导出函数。

方法名字必须以Java开头,然后包名和类名及方法名之间下划线隔开。假设不巧刚好你的包名中有下划线。那怎样处理JNI中java包名含下划线情况呢?在前面加一个“1”。


这么简单程序,遇到几个错误:

第一个是说JNI Load Library失败,由于apk中能够看到so是不是被压缩进去了(更改apk后缀为rar,解压rar能够看到有个lib目录内有这个so),我这边看到压缩进去了,结果还是载入失败。

原因在于loadLibrary的參数必需要不带前缀lib不加后缀.so才干够。

爆出undefined reference to。原因是因为我没有声明extern "C"。java找不到C++声明方式的。

还有就是包名中恰好出现下划线。比方JNI_Learn,须要更改为_1才干够规避。

还有就是使用LOG,必需要在Android.mk中添加LOCAL_LDLIBS。



版权声明:本文博客原创文章。博客,未经同意,不得转载。

更多相关文章

  1. Android(安卓)滑动冲突处理
  2. Android(安卓)Alarm定时任务基础
  3. 五种控制Android应用的权限的方法
  4. Android(安卓)listview 加载更多定位问题
  5. postInvalidate(),invalidate(),requestLayout的区别
  6. Android(安卓)NDK开发的环境配置和使用
  7. Android复杂数据模型序列化
  8. Android(安卓)BaseAadapter 异步加载图片方法
  9. EventBus从入门到装逼,源码分析,手撸框架

随机推荐

  1. android 私有文件的读写
  2. Android中对于onMeasure()的理解
  3. android webrtc 视频旋转
  4. android注解Butterknife的使用及代码分析
  5. 在js和java中判断手机访问的是ios系统还
  6. 【凯子哥带你学Framework】Activity界面
  7. 学习Android从0开始之基础篇(5)- Button简
  8. 热修复
  9. Android(安卓)Activity 启动模式(Launch M
  10. android sdk 无法更新问题——终极更新版