参考资料:ORB_SLAM2在Android上的移植
ORB_SLAM2_Android—github
OpenCV4Android

本来想直接下载github上的工程import,但是不知道为什么直接导入后eclipse直接卡死,不管怎么配置SDK、NDK、ADT各种都没用,所以只能自己移植,折腾了好久还顺便学了下Android,终于搞定了。

关于Android的移植网上的资料非常多也非常杂。虽然很多博客写的很好,但是还是推荐直接看官方文档。

Android环境配置

首先是JDK的配置,很简单百度一下,最后做个测试:
在命令行输入Java -version,如果出现以下类似内容则配置成功:

然后下载完Eclipse后,Java的环境配置好了,但是Android的开发,还需要以后步骤:
1.ADT,有在线安装和离线包两种方式,在线方法为:
在Eclipse-> “Help” -> “Install New Software” ->Add ,出现下图所示后Name随便取,Location输入http://dl-ssl.google.com/android/eclipse 确认后按提示一步一步next就OK了。

离线方式前面也一样,只是不是直接填Location,而是先下载离线包,然后点击Archive选择压缩包

2.Android SDK,建议从官网下载(需要科学上网),SDK官网下载 网上下载说不定就会掉坑,不要问我为什么知道。。下载并解压后(路径不要有中午),在Eclipse中选择Window–>preferences ->Android 在Android Location里填入解压的根目录,则Android环境配置基本完成。如下图所示:

这时候你的菜单栏应该有了这两项 :

分别是SDK和AVD(模拟器)
PS:如果配置完后运气不好没有出现也没事(没错就是我),先在Eclipse点Window,如果有下图这样的SDK和AVD,那么就证明并不是配置失败了,而是设置问题。

设置方法:Windows–>Customize Perspective,选择Command Groups Availability选项,确保Android SDK and AVD Manager是勾选上的,然后选择Tool Bar Visibility选项—>勾选Android SDK and AVD Manager,这两个顺序不能反,OK后好了~

3.更新SDK,在更新之前,建议先科学上网,这个需要连接外网。当然网上有更改host文件的方法,可以自行搜索。点刚刚那个左边的图标,界面如下:

其中有许多文件,但是不需要全下!不需要全下!不需要全下!
Tools全下,然后每个版本的SDK Platform、Sources for Android SDK全下,Googel APIs在天朝一般用不到可以不下,主要要提System Image,镜像是模拟器,只用下自己需要模拟器的版本就可以了,都下的话超大超久,血泪教训,Extras建议下载。
具体内容可以参考知乎:Android SDk里面到底哪些东西是必须下载的

———至此Android开发环境就配置好了—-
4.NDK配置。下载官网最新版本的NDK NDK官网下载(需要科学上网)。网上直接下说不定就有坑。。而且这个坑还根本看不出来,还是官网安全。而且低版本r7以下还需要cygwin,7以上的新版就不用了。
先在环境变量里配置NDK的根目录(这一步在命令行操作的时候挺重要的),解压后(规则同sdk),打开Eclipse,点击Window–>Preferences,选择Android–>NDK,在右边界面中填入NDK Location即可。

先测试一下NDK是否配置好(翻译官网提供的教程):
打开Eclipse,File->import->Android->Existing Android Code Into Workspace(这里不要直接在General里选择Existing Projects Into Workspace,是找不到例程的,我刚开始这样还以为是NDK配置问题,还蠢蠢的重新弄,走了好多弯路)
->Browse->/samples/,加入HelloJni工程,(最新版的NDK不知道为什么不提供例程了,可以下r10b版本然后导入)。
导入后,右键select Android Tools > Add Native Support,Accept the default library name (“hello-jni”), and click Finish.
这时候菜单栏应该会出现一个小锤子图标。点击Build,在模拟器或者真机运行后如下图所示则配置成功:


Android移植基础

NDK是集成的Android中调用C++代码的工具包,核心是JNI(Java Native Interface)技术,具体这里略过不表。只说说NDK开发的基本步骤:
编写Java代码:在Java中定义一个类,比如说叫NDKHelper吧,里面定义几个java的方法,只需要声明,不需要实现,如下所示:

public class NDKHelper {    //NDK示例方法1    public static native void ndkOne(int a,long b);    //NDK示例方法2    public static native int ndkTwo(String a,String b);}

native标识符表示该函数将会利用C++代码完成实现。
接下来在工程上右键,Android Tools–>Add native support
名字就是最后我们要生成的库的名字,随便填,可修改。点击确定就会给你的工程添加C++编译支持,菜单栏会多了个小锤子,这个是用来编译C++的快捷键。在你的工程目录下会新建jni目录和obj目录,其中jni目录用来存放和C++代码有关的东西,obj则存放C++进行编译时产生的中间件,最后生成的library会写入到libs文件夹下。
在jni文件夹中生成了如下文件,一个.cpp,一个Android.mk,其中.cpp是自动生成的,是用来编写C++部分的,而Android.mk类似C++里面的CMakeList,用来指定需要编译的文件和编译生成的模块名,一个最简单的Android.mk文件如下所示:

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE    := NDKTestLOCAL_SRC_FILES := NDKTest.cppinclude $(BUILD_SHARED_LIBRARY)

LOCAL_PATH :=(callmydir)include(CLEAR_VARS)表示清除全部非系统变量和部分系统变量;
LOCAL_MODULE := NDKTest 表示当前生成的模块名,最终会生成libNDKTest.so文件
LOCAL_SRC_FILES := NDKTest.cpp 表示当前需要编译的cpp文件;
include $(BUILD_SHARED_LIBRARY) 表示生成共享库,需要生成静态库请修改成BUILD_STATIC_LIBRARY。

其他基础命令:
LOCAL_C_INCLUDES:= 表示添加头文件进入编译环境
LOCAL_LDLIBS:= 表示添加系统静态库
LOCAL_SHARED_LIBRARIES:= 表示添加共享库
其他命令请自行查看API文档。

这里指定了进行编译时的各项条件,如果需要指定编译器版本和编译目标平台等信息,则需要在jni目录下新建Application.mk文件。
接下来编写对应的C++文件。
打开eclipse,点击Project–>build Project(若build automatically已勾选则会自动编译)打开命令行,cd到你的工程文件夹下的bin–>classes文件夹下,输入如下命令:
javah com.example.ndktest.NDKHelper
回车,则在你的classes文件夹下会生成对应的头文件。这里com.example.ndktest是你的package名字,NDKHelper是你的NDK函数的类名。
就会生成头文件。其他不用管,我们关注中间的两个函数声明:

JNIEXPORT void JNICALL Java_com_example_ndktest_NDKHelper_ndkOne(JNIEnv *, jclass, jint, jlong);1

这个函数就是NDKHelper类中ndkOne函数对应的C++版本,其中JNIEXPORT和JNICALL是固定字段,void是函数返回值,函数名由Java字段+包名+类名+函数名组成,参数则多了几个JNI的系统参数JNIEnv 和jclass,其他的就是NDKHelper类中的对应参数,ndk会对该函数进行解析和链接,实现java和C++的对接。
将生成的.h头文件复制到jni目录下,新建对应的cpp文件,将该头文件include进来并对对应函数进行实现,实现过程就视函数功能而定。
这些工作完成后需要修改你的Android.mk文件,将刚刚新建的cpp和h文件包括进来。
然后点击开始那个小锤子或者直接项目右键RunAs–>Android Application,则C++部分会开始编译,编译具体过程可以在Eclipse下方Console窗口看到(如果没有Console窗口则点击Window–>Show Views,选择Console确定即可)。
编译完成后会生成对应的库存放在libs目录下,则你可以开始在Java里面调用刚才定义的ndkOne和ndkTwo函数实现具体的功能。


ORB_SLAM2移植

先新建一个Android工程,建议不要把版本兼容到4.0以下,会出现一些奇奇怪怪的事情,这里我选择新建4.4.2的工程。
然后复制原工程的res文件夹替换掉自己工程下的文件夹,这里包括了所需的图片、存放在res/values/strings.xml的字符、res/layout下的各种布局;复制原工程的AndroidManifest.xml替换新建工程下的xml,复制完之后,意料之中报错啦,这是因为还没有链接OpenCV库,而在布局里有用到。

OpenCV库配置(参考官方文档)
先去官网下载opencv4android:
OpenCV官网下载
解压后,可以参考/docs/opencv_tutorials.pdf 感觉比很多博客讲的都更清楚
根据例程测试过问问题后,导入workspace,然后右键我们的ORB_SLAM2_Android工程->properties->Android,在右下Library里Add OpenCV库,如下图所示:


这样之后就暂时没有报错了

按照之前Android移植基础里讲的办法生成小锤子、jni、libs文件夹,然后复制原工程的.java文件到src,如下图所示:

其中OrbNdkHelper.java文件是关键的native标识符所在的类,代码如下:

public class OrbNdkHelper {    /**     * jni     * @param VOCPath     * @param calibrationPath     */    public static native void initSystemWithParameters(String VOCPath,String calibrationPath);    public static native int[] startCurrentORB(double curTimeStamp,int[] data,int w,int h);    public native static int[] startCurrentORBForCamera(double curTimeStamp,long addr,int w,int h);    public native static void glesInit();      public native static void glesRender();      public native static void glesResize(int width, int height);}

然后在命令行cd到工程根目录/bin/classes,输入javah orb.slam2.android.nativefunc.OrbNdkHelper生成.h文件,并复制到jni文件夹,然后复制原工程jni目录下的其他文件到本工程的jni,如下图所示:

这时候大概的文件都已经导入完毕了,但是我出现了许多的报错,以下是填坑过程。

1.orb_slam2_android_nativefunc_OrbNdkHelper.cpp里有几个报错:

JNIEXPORT void JNICALL Java_orb_slam2_android_nativefunc_OrbNdkHelper_initSystemWithParameters(JNIEnv * env, jclass cls, jstring VOCPath, jstring calibrationPath) {    const char *calChar = env->GetStringUTFChars(calibrationPath, JNI_FALSE);    const char *vocChar = env->GetStringUTFChars(VOCPath, JNI_FALSE);    // use your string    std::string voc_string(vocChar);    std::string cal_string(calChar);    JavaVM *jvm=NULL; //增加的一句    env->GetJavaVM(&jvm);    jvm->AttachCurrentThread(&env, NULL);    s=new ORB_SLAM2::System(voc_string,cal_string,ORB_SLAM2::System::MONOCULAR,true);    env->ReleaseStringUTFChars(calibrationPath, calChar);    env->ReleaseStringUTFChars(VOCPath, vocChar);    init_end=true;}

这段代码里面的:

JavaVM *jvm=NULL; //增加的一句

是我增加的,如果不增加的话,后两句会报错无法识别jvm这个变量,我搜索了全部工程也找不到jvm,所以只能自己先增加一个;
还有一个地方是:

resultPtr = env->GetIntArrayElements(resultArray, 0);

有3个地方用到GetIntArrayElements这个函数,全工程的第二个参数是false,这个在我这里是报错的,然后我百度了挺久,发现这个函数的声明是:

 jint* GetIntArrayElements(jintArray array, jboolean* isCopy)

原工程的flase不能被程序认定为jboolean格式,然后在jni.h顺藤摸瓜找到了以下定义:

#define JNI_FALSE   0#define JNI_TRUE    1

于是把原来的“false”改成“JNI_FALSE”或者0,就可以通过了!

2.在用NDK-r10b版本的时候ORB_SLAM2文件夹和第三方文件夹出现大量报错,很多变量无法找到,这里的解决办法是:
改到r13b最新版本,然后在Application.mk文件里,NDK_TOOLCHAIN_VERSION := 4.8–>改到4.9

APP_STL := gnustl_staticAPP_CPPFLAGS := -frtti -fexceptions -mfloat-abi=softfp -mfpu=neon -std=gnu++0x -Wno-deprecated \-ftree-vectorize -ffast-math -fsingle-precision-constantNDK_TOOLCHAIN_VERSION := 4.9APP_CFLAGS := --std=c++11APP_ABI :=armeabi-v7aAPP_OPTIM := releaseAPP_SHORT_COMMANDS      := true

更多相关文章

  1. Android周学习Step By Step(7)--Activity简介
  2. Android应用的跨语言调用小结
  3. Android开发——了解android项目目录结构
  4. Delphi Android(安卓)USB声明文件
  5. LIstview的使用和数据填充
  6. mtk android tp 调试
  7. 箭头函数的基础使用
  8. NPM 和webpack 的基础使用
  9. Python技巧匿名函数、回调函数和高阶函数

随机推荐

  1. android 系统级 bug audio latency
  2. android 颜色值 代码
  3. 在native c++里打log
  4. 使用TextView实现跑马灯Marquee
  5. Android(安卓)自定义View onDraw方法详解
  6. Android 剪贴板详解
  7. Android开发 设置控件边角半圆
  8. 简单研究Android View绘制一 测量过程
  9. android:imeOptions属性
  10. Android 编译时注解