参考:

java jni 入门1 - 一个简单的从Java程序中调用C函数 : http://blog.csdn.net/u012005313/article/details/49644283



#########################################################


之前也接触过NDK和JNI,但是并没有很好的结合NDK和JNI来总结关于so文件的制作和使用。现在把最近一段时间的接触的关于so的制作和使用总结一下。


还是从最简单的例子开始:android apk调用一个C函数,输出一个log记录,并返回一个字符串“Hello JNI”


##############################################################3


新建一个工程SoDemo



后面一直选择Next/Finish即可完成新建工程



修改activity_main.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>        

功能介绍:加入一个文本框和按钮。apk运行后,点击按钮调用C程序,文本框显示返回的字符串


修改MainActivity.java代码如下:

package com.zj.sodemo;import android.app.Activity;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity {    private Button mButton;    private TextView mTextView;        private String text = null;    static {        System.loadLibrary("JNITest");    }        public native String helloJNI();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mButton = (Button)findViewById(R.id.button);        mTextView = (TextView)findViewById(R.id.text);        mButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                text = helloJNI();                mTextView.setText(text);            }        });    }}
功能介绍:新建文本框和按钮,同时调用so库JNITest,调用so库里面的函数是helloJNI,同时为按钮建立一个点击监听器,点击按钮,则调用helloJNI()函数,并显示返回的字符串。


至此,前期准备工作都已完成

##########################################################3


接下来需要使用JDK工具javah来建立java和C/C++之间的联系

参考文档: Android Studio & NDK: I got an error when “javah -d jni -classpath…” - http://stackoverflow.com/questions/27252712/android-studio-ndk-i-got-an-error-when-javah-d-jni-classpath


在  android ndk 入门 - 一个简单的ndk工程 : http://blog.csdn.net/u012005313/article/details/49911693 中,已经介绍了如何在android studio中配置javah

下面,我介绍一种使用命令行的方式

首先你需要先生成MainActivity.java的class文件,点击菜单栏build->Make Project(快捷键Ctrl + F9)即可编译整个工程。编译完成后,在路径app/build/intermediates/classes/debug/com/zj/sodemo下应该会出现MainActivity.class文件


android studio配置了控制台窗口,在窗口底部工具栏中应该有Terminal选项


如果不存在,则点击顶部菜单栏View->Tool Windows->Terminal(快捷键Ctrl + F12)就会弹出控制台窗口


进入main目录并新建文件夹jni

cd app/src/main/mkdir jni


运行以下命令:

javah -d jni -classpath /opt/android-sdk-linux/platforms/android-24/android.jar:../../build/intermediates/classes/debug/ com.zj.sodemo.MainActivity
命令介绍:-d参数-输出目录

-classpath-从中加载类的路径。没有配置android.jar环境变量的话就需要在这里加入(注意,android.jar后面跟的是一个冒号:,而不是分号;

com.zj.sodemo.MainActivity是生成JNI样式的表头文件

在这里我们将生成的.h文件保存在jni文件夹内:


打开文件com_zj_sodemo_MainActivity.h:

/* DO NOT EDIT THIS FILE - it is machine generated */#include /* Header for class com_zj_sodemo_MainActivity */#ifndef _Included_com_zj_sodemo_MainActivity#define _Included_com_zj_sodemo_MainActivity#ifdef __cplusplusextern "C" {#endif#undef com_zj_sodemo_MainActivity_BIND_ABOVE_CLIENT#define com_zj_sodemo_MainActivity_BIND_ABOVE_CLIENT 8L#undef com_zj_sodemo_MainActivity_BIND_ADJUST_WITH_ACTIVITY#define com_zj_sodemo_MainActivity_BIND_ADJUST_WITH_ACTIVITY 128L#undef com_zj_sodemo_MainActivity_BIND_ALLOW_OOM_MANAGEMENT#define com_zj_sodemo_MainActivity_BIND_ALLOW_OOM_MANAGEMENT 16L#undef com_zj_sodemo_MainActivity_BIND_AUTO_CREATE#define com_zj_sodemo_MainActivity_BIND_AUTO_CREATE 1L#undef com_zj_sodemo_MainActivity_BIND_DEBUG_UNBIND#define com_zj_sodemo_MainActivity_BIND_DEBUG_UNBIND 2L#undef com_zj_sodemo_MainActivity_BIND_EXTERNAL_SERVICE#define com_zj_sodemo_MainActivity_BIND_EXTERNAL_SERVICE -2147483648L#undef com_zj_sodemo_MainActivity_BIND_IMPORTANT#define com_zj_sodemo_MainActivity_BIND_IMPORTANT 64L#undef com_zj_sodemo_MainActivity_BIND_NOT_FOREGROUND#define com_zj_sodemo_MainActivity_BIND_NOT_FOREGROUND 4L#undef com_zj_sodemo_MainActivity_BIND_WAIVE_PRIORITY#define com_zj_sodemo_MainActivity_BIND_WAIVE_PRIORITY 32L#undef com_zj_sodemo_MainActivity_CONTEXT_IGNORE_SECURITY#define com_zj_sodemo_MainActivity_CONTEXT_IGNORE_SECURITY 2L#undef com_zj_sodemo_MainActivity_CONTEXT_INCLUDE_CODE#define com_zj_sodemo_MainActivity_CONTEXT_INCLUDE_CODE 1L#undef com_zj_sodemo_MainActivity_CONTEXT_RESTRICTED#define com_zj_sodemo_MainActivity_CONTEXT_RESTRICTED 4L#undef com_zj_sodemo_MainActivity_MODE_APPEND#define com_zj_sodemo_MainActivity_MODE_APPEND 32768L#undef com_zj_sodemo_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING#define com_zj_sodemo_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L#undef com_zj_sodemo_MainActivity_MODE_MULTI_PROCESS#define com_zj_sodemo_MainActivity_MODE_MULTI_PROCESS 4L#undef com_zj_sodemo_MainActivity_MODE_NO_LOCALIZED_COLLATORS#define com_zj_sodemo_MainActivity_MODE_NO_LOCALIZED_COLLATORS 16L#undef com_zj_sodemo_MainActivity_MODE_PRIVATE#define com_zj_sodemo_MainActivity_MODE_PRIVATE 0L#undef com_zj_sodemo_MainActivity_MODE_WORLD_READABLE#define com_zj_sodemo_MainActivity_MODE_WORLD_READABLE 1L#undef com_zj_sodemo_MainActivity_MODE_WORLD_WRITEABLE#define com_zj_sodemo_MainActivity_MODE_WORLD_WRITEABLE 2L#undef com_zj_sodemo_MainActivity_DEFAULT_KEYS_DIALER#define com_zj_sodemo_MainActivity_DEFAULT_KEYS_DIALER 1L#undef com_zj_sodemo_MainActivity_DEFAULT_KEYS_DISABLE#define com_zj_sodemo_MainActivity_DEFAULT_KEYS_DISABLE 0L#undef com_zj_sodemo_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL#define com_zj_sodemo_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L#undef com_zj_sodemo_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL#define com_zj_sodemo_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L#undef com_zj_sodemo_MainActivity_DEFAULT_KEYS_SHORTCUT#define com_zj_sodemo_MainActivity_DEFAULT_KEYS_SHORTCUT 2L#undef com_zj_sodemo_MainActivity_RESULT_CANCELED#define com_zj_sodemo_MainActivity_RESULT_CANCELED 0L#undef com_zj_sodemo_MainActivity_RESULT_FIRST_USER#define com_zj_sodemo_MainActivity_RESULT_FIRST_USER 1L#undef com_zj_sodemo_MainActivity_RESULT_OK#define com_zj_sodemo_MainActivity_RESULT_OK -1L/* * Class:     com_zj_sodemo_MainActivity * Method:    helloJNI * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_zj_sodemo_MainActivity_helloJNI  (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif


里面有函数声明JNIEXPORT jstring JNICALL Java_com_zj_sodemo_MainActivity_helloJNI

接下来就是实现该函数声明


#############################################3

生成.h文件后我们就可以编写相应的C/C++实现代码


在jni目录下新建main.cpp,代码如下:

#include #include #include #include "com_zj_sodemo_MainActivity.h"using namespace std;#define LOG_TAG "zj"#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)extern "C"{/* * Class:     com_zj_sodemo_MainActivity * Method:    helloJNI * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_zj_sodemo_MainActivity_helloJNI  (JNIEnv *env, jobject obj)  {    LOGI("now in jni world");    return env->NewStringUTF("Hello JNI");  }}

程序介绍:

1.生成so文件需要头文件jni.h;

2.输出log需要头文件android/log.h;

3.需要包含头文件com_zj_sodemo_MainActivity.h并实现其中声明的函数

4.如果使用C++代码,则必须实现本地方法的声明extern "C"(阻止C++编译器生产C++特有的代码)

5.JNICALL Java_com_zj_sodemo_MainActivity_helloJNI定义中实现了一条记录的输出,并返回一个字符串


#################################################


参考:

android studio 使用 jni 编译 opencv 完整实例 之 图像边缘检测!从此在andrid中自由使用 图像匹配、识别、检测 - http://www.cnblogs.com/linguanh/p/4624768.html?utm_source=tuicool&utm_medium=referral

android ndk 入门之打印log信息 - http://blog.csdn.net/qiuxiaolong007/article/details/7548580


接下来就是生成so库


在目录jni中新建Android.mk:

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := JNITestLOCAL_SRC_FILES := main.cppLOCAL_LDLIBS +=-L$(SYSROOT)/usr/lib -lm -lloginclude $(BUILD_SHARED_LIBRARY)

新建Application.mk:

APP_STL := gnustl_staticAPP_CPPFLAGS := -frtti -fexceptionsAPP_ABI := armeabi-v7a       #这句是设置生成的cpu指令类型,提示,目前绝大部分安卓手机支持armeabi,libs下太多类型,编译进去 apk 包会过大APP_PLATFORM := android-8    #这句是设置最低安卓平台,可以不弄

打开android stdio的控制台窗口,进入jni路径,运行命令ndk-build:



运行成功,同时生成so库libJNITest.so,位于目录libs/armeabi-v7a中:



###############################


有两种方式使用so库。

1.android studio默认调用src/main/jniLibs下的so文件;

2.通过配置,可以使用src/main/libs下的so文件


我们现在实现第2种。打开app/build.gradle文件,在android{}内加入:

    sourceSets {        main() {            jniLibs.srcDirs = ['src/main/libs']            jni.srcDirs = []        }    }

同时,在gradle.properties文件中加入语句:

android.useDeprecatedNdk=true

编译整个工程:点击顶部菜单栏Build->Make Project

编译完成后点击运行按钮(Run 'app',快捷键Shift + F10)




点击按钮





更多相关文章

  1. android类作用整理
  2. 修改Android镜像文件 ramdisk.img、system.img、userdata.img获
  3. Android中的Service使用
  4. Android(安卓)Camera 运行流程
  5. Js Android(安卓)交互
  6. Android(安卓)5.0(Lollipop)事件输入系统(Input System)
  7. Android安全/开发基础--15--应用程序配置文件详解(AndroidManifes
  8. Android(安卓)图片的裁剪与相机调用
  9. Android(安卓)studio将项目转换为jar文件

随机推荐

  1. Relativelayout
  2. Android(安卓)开发入门问题集:启动模拟器
  3. Android之子线程更新UI
  4. android GridView item中组件获取焦点
  5. android服务学习service之AIDL
  6. 第六章(3) Android中的Drawable
  7. Android(安卓)混淆代码问题总结
  8. Android(安卓)Studio调试native或者servi
  9. 如何设置Activity全屏 设置Activity非全
  10. Android对system_server中binder的ioctl