zoukankan      html  css  js  c++  java
  • Android NDK进入发展

    使用互联网有很多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 := -llog
    
    LOCAL_MODULE    := JNI_Learn
    LOCAL_SRC_FILES := JNI_Learn.cpp
    
    include $(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。



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

  • 相关阅读:
    IOS的系统手机 宽度无法自适应 解决办法
    iframe 设置背景透明
    thinkphp5 常用的2个方法
    thinkphp引入后台模板文件的路径怎么写?
    html的confirm()
    php 如何往数组里添加数据
    thinkphp51 重定向 redirect()
    【Oracle 触发器】(4)触发器应用场景--数据的确认
    【Oracle 触发器】(3)触发器应用场景--复杂的安全性检查
    【Oracle 触发器】(2)触发器的分类(语句级/行级)
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4680473.html
Copyright © 2011-2022 走看看