之前已经说过如何在 linux 中使用 java 调用 so 动态链接库
这里来说一下在 android 中调用 so 动态链接库
作者之前也认为能够使用 java 调用 so 动态链接库之后便可以在 android 同样实现,但是发现将 so 文件导入 android 项目后,启动时导入动态链接库总是报错
错误为:Cannot load libraray 、not a avlid ELF 。。。 具体错误描述记不太清楚了,如果有大神知道具体原因麻烦留言告知下小弟
废话不说了,开始吧
在 android 中使用 so 动态链接库需要使用到 NDK
目前最新版为 android-ndk-r9
首页地址:http://developer.android.com/tools/sdk/ndk/index.html
下载地址:https://dl.google.com/android/ndk/android-ndk-r9-windows-x86.zip
下载完成后解压到电脑中,路径中不可出现中文名称
1、新建 Android Application Peoject,项目名称为 JNIDemo
2、在项目根目录下建立 jni 目录,将需要编译的 .c 文件拷贝到 jni 目录下
3、在 jni 目录下建立 Android.mk 文件并编辑
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := main
LOCAL_SRC_FILES := source.c
include $(BUILD_SHARED_LIBRARY)
我们需要修改的只有 LOCAL_MODULE 和 LOCAL_SRC_FILES 的值
LOCAL_MODULE 指定生成的 so 文件的名称,生成成功后会自动为该文件添加 lib 前缀和 .so 后缀,即生成成功的完整文件名为 libmain.so
LOCAL_SRC_FILES 指定的是需要编译的 c 文件
4、将 JNIDemo 转换为 C/C++ 项目
在 JNIDemo 项目上右键 New >> Other >> C/C++ >> Convert to a C/C++ Project
进入如下界面后选项如下图,配置完成后 Finish
5、右键选择 JNIDemo 项目,选择 Properties
选中左侧 C/C++ Build 选项,然后在 Builder Setting 选项卡中将 Build command 的值更改为你的电脑上 NDK 的构建文件绝对路径
如:D:\android-ndk-r9\ndk-build.cmd
然后切换到 Behaviour 选项卡,将 Build(Incremental build)的值删掉
最后在左侧的列表中展开 C/C++ General ,选中 Paths and Symbols,在右侧 Languages 中选中 GUN C,然后点击 Add,选择 File System
指定到如下路径下:D:\android-ndk-r9\platforms\android-8\arch-arm\usr\include
其中 android-8 为你的项目中使用的 sdk 版本,需要对应上,然后点击 OK,接着在项目上点击右键,选择 Build Project
构建完项目之后会发现项目中的 libs/armeabi 目录下已经添加好了我们指定的 libmain.so 文件,那我们现在就可以开始准备测试了~~
注:本库中使用的接口文件代码 source.c
#include "stdio.h"
#include "jni.h"
JNIEXPORT jstring JNICALL Java_com_hongquan_JNIInterfaces_sayHi(JNIEnv *env, jobject jo, jstring name)
{
return name;
}
6、在 JNIDemo 中新建类 JNIInterface,包名为 com.hongquan,代码如下
package com.hongquan;
public class JNIInterfaces {
// 载入动态链接库
static {
System.loadLibrary("main");
}
// 声明动态库接口
public native String sayHi(String str);
}
7、在 JNIDemo 项目的启动类中调用接口函数进行测试
package com.hongquan;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
JNIInterfaces lib = null;
TextView tvInfo;
EditText etInfo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lib = new JNIInterfaces();
tvInfo = (TextView) findViewById(R.id.txtInfo);
etInfo = (EditText) findViewById(R.id.etInfo);
findViewById(R.id.myBtn).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (etInfo.getText().toString().trim().length() <= 0) {
Toast.makeText(getApplicationContext(), "请输入文本内容", 1).show();
return;
}
tvInfo.setText("so return: " + etInfo.getText());
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return false;
}
}
android 中调用 so 动态链接库就完成啦~~
so 动态链接库下载地址:http://pan.baidu.com/s/1Bqsop
JNIDemo 项目下载地址:http://pan.baidu.com/s/1668Z8