android JNI 开发笔记第三方库调用

本文详细介绍如何在Eclipse中配置Android NDK环境,包括下载和安装NDK、CDT和ADT插件,配置SDK路径,以及创建和管理C/C++项目。同时,文章深入讲解如何使用NDK调用C++代码库和第三方库,提供具体步骤和代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(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标签页下,添加如下路径。

 
  1. $NDK_PATH\platforms\android-19\arch-arm\usr\include

  2. $NDK_PATH\sources\cxx-stl\gnu-libstdc++\4.8\include

  3. $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    := thirdLib

    LOCAL_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问题


  • 错误描述

    调用memcpyvector.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错误也会被忽略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值