(1)下载NDK包,并解压http://developer.android.com/tools/sdk/ndk/index.html
(2)下载CDT(C/C++开发环境插件),在Eclipse中安装此插件。
(3)下载ADT,在Ecplise中安装此插件,一定要选中NDK Plugin
(4)在Ecplise中配置Android SDK和NDK SDK的路径,在Eclipse的Window->Preferences->Android中设置,我本机的设置为Android SDK Location为“C:\Android\android-sdk”,NDK Location为“F:\hexm_private\Android\android-ndk-r8e”。
(1)首先在Eclipse中创建一个Android工程
(2)在Package Explorer中选中刚才创建的Android工程,右键选择Android Tools -> Add Native Support..,填写需要生成的动态库的名称,比如“HelloWorld”,也可以是别的,你会发现工程中多了一个叫做“jni”的目录,并自动生成了一个C++文件和一个Androd.MK文件,所有的C++源代码就放在这个目录中。这样,就跟Eclipse工程添加了C/C++属性,就能够用CDT插件在Eclipse中进行C/C++开发了。
添加NDK库相关路径
在菜单栏Project -> Propertis
中,C/C++ General -> Paths and Symbols
下,Include
标签页下,添加如下路径。
-
$NDK_PATH\platforms\android-19\arch-arm\usr\include
-
$NDK_PATH\sources\cxx-stl\gnu-libstdc++\4.8\include
-
$NDK_PATH\sources\cxx-stl\gnu-libstdc++\4.8\libs\armeabi-v7a\include
注:此时,
Unresolved inclusion
提示应已经消失,但仍存在Symbol 'string' could not be resolved
之类提示。
1.jni调用C++代码库
- 一个android工程,命名为
Engine
。 - 创建jni目录
- 在刚刚的工程中,我们新建一个包
com.bobo.utils
,并在该包中创建NativeClass.java
文件,该类就用于加载动态库并调用native方法。 - 编写NativeClass方法
- 找到生成的NativeClass.class,根据NativeClass中package路径,用cmd命令窗口进入到com文件夹的上一级目录
- 确认系统java环境变量和开发环境变量一致,否则生头文件会出问题,利用javah命令产生JNI头文件
- 可以在com相同目录下找到生成的头文件com_bobo_utils_NativeClass.h
- 头文件信息:
- 将产生的头文件放在jni目录下
- 在jni目录下创建实现文件Test.cpp,根据头文件编写,删除头文件
- 注意:这里.cpp文件如图,.c文件为(*env)->NewStringUTF(env, "hello JNI!");调用方式不同。
- 如果发现JNIEnv等报没定义的错误,是由于没有将jni.h导入的缘故,而这个文件在ndk的目录下面。所以,参照以下步骤:
Project Properties -> C/C++ General -> Path and Symbols
选择include标签,Add -> $Android_NDK_HOME/platforms/android-14/arch-arm/usr/include
且选中All languages.
最后Apply -> OK - 编写Android.mk
- 编写Application.mk
- 使用命令行cmd 进入到jni目录下,执行ndk-build 命令
- 可以看见在lib目录下生成了.so库
- 修改NativeClass.java,加载生成的动态库
- 修改MainActivity
-
import android.widget.Toast;
public class MainActivity extends Activity {
private Button button1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1 = (Button)findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener()
{@Override
public void onClick(View v) {
String str = "aa";
CharSequence a = NativeClass.engine(str);
Toast.makeText(getApplicationContext(), a,Toast.LENGTH_SHORT).show();
}
} );
}@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}}
- 运行效果
2.android调用第三方C++库
- 在上一个例子的基础上C++开始学习第三方库diao调用
- 首先创建一个第三方库,在jni目录下创建thridLib.h,thirdLib.cpp
-
.h文件:
#ifndef THIRDLIB_H_
#define THIRDLIB_H_#include <string>
class ThirdLib {
public:
ThirdLib();
virtual ~ThirdLib();
char* useC(const char*);
};#endif /* THIRDLIB_H_ */
- .cpp文件:
-
#include "ThirdLib.h"
ThirdLib::ThirdLib() {
// TODO Auto-generated constructor stub}
ThirdLib::~ThirdLib() {
// TODO Auto-generated destructor stub
}
char* ThirdLib::useC(const char* )
{
std::string a = "welcome to c";
return &a[0];
} -
放在如图所示目录
-
-
修改Android.mk用于编译第三方库
-
#Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := thirdLibLOCAL_SRC_FILES := thirdLib.cpp
include $(BUILD_SHARED_LIBRARY)
-
使用命令行cmd 进入到jni目录下,执行ndk-build 命令生成libThirdLib.so
-
将头文件和生成的动态库放在如图所示位置
-
-
修改Test.cpp如下
-
#include <jni.h>
#include "lib/include/thirdLib.h"
#include <string>
extern "C" {/*
* Class: com_bobo_utils_NativeClass
* Method: engine
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_bobo_utils_NativeClass_engine
(JNIEnv *, jclass, jstring);JNIEXPORT jstring JNICALL Java_com_bobo_utils_NativeClass_engine
(JNIEnv *env, jclass, jstring b)
{
thirdLib test;
const char *strContent = env->GetStringUTFChars(b, JNI_FALSE);
jstring jstr = (*env).NewStringUTF((char*)test.useC(strContent));
return jstr;
}}
-
修改android.mk如下
-
#Android.mk
LOCAL_PATH := $(call my-dir)#第三方的编译模块
include $(CLEAR_VARS)
LOCAL_MODULE := thirdLib
LOCAL_SRC_FILES := lib/libthirdLib.so
#下面是申明第三方头文件路径
LOCAL_EXPORT_C_INCLUDES := lib/include
include $(PREBUILT_SHARED_LIBRARY)#自己的编译模块
include $(CLEAR_VARS)
LOCAL_MODULE := Test
LOCAL_SRC_FILES := Test.cpp
LOCAL_LDLIBS += -L$(SYSROOT)/lib -llog
LOCAL_CFLAGS := -g
#这里引入第三方编译模块
LOCAL_SHARED_LIBRARIES := thirdLib
include $(BUILD_SHARED_LIBRARY)
使用命令行cmd 进入到jni目录下,执行ndk-build 命令生成libTest.so -
更改NativeClass.java,加载第三方库
package com.bobo.utils;
public class NativeClass {
static
{
System.loadLibrary("test");
System.loadLibrary("thirdLib");
}
public static native String engine(String str);
} -
-
运行程序Test
-
-
点Button,可以看到打印出第三方库字符串
Invalid arguments
问题-
错误描述
调用
memcpy
、vector.resize()
等函数时,Eclipse提示 -
Invalid arguments '
-
Candidates are:
-
void resize(?)
-
void resize(?, const float &)
-
'
-
临时解决方案
Project -> Propertis
中,修改C/C++ General -> Code Analysis
配置,将Invalid arguments
项由Error
修改为Warning
。
尽管该方法会解决我们的问题,但会导致真正的Invalid arguments
错误也会被忽略。