android在eclipse环境下的ndk开发环境配置

1 简介

  android平台需要使用C/C++语言编写的库需要经过JNI(Java Native Interface)。JNI是一种编程框架,JNI允许运行于JVM的Java程序调用本地的C/C++以及其他高性能语言编写的代码。JNI有两种调用方式:

  • java代码调用native的代码。这种方式比较常用,本文只涉及这种方式。
  • native代码调用java代码。

  android项目调用本地代码的基本步骤如下:

  1. 创建一个Java类,在该类中创建一个包含native修饰符修饰的方法;
  2. 使用java编译器javac编译1步骤创建的java类生成对应的.class文件;
  3. 利用生成的.class文件作为输入使用javah命令生成对应的JNI头文件;
  4. 为生成的JNI的头文件创建对应的cpp实现文件,并在该文件中实现对应的cpp函数;
  5. 编写自动化编译配置文件Android.mk,将其和4步骤的实现文件和3步骤的头文件存放在同一文件夹下利用ndk-build生成对应的动态链接库。
  6. 在Java类中加载动态链接库并调用该Native方法。
      能够看到的是1-5是生成动态库的过程,而6-7是调用动态库的过程。以上过程都可以手动编译进行,但是这里不打算采用这种方式,下面主要讲如何配置eclipse自动使用上面的命令进行ndk开发。

2 预置环境

  基本的开发环境为eclipse的安卓开发环境配套的SDK和生成动态库需要的编译工具链:jdk+eclipse+android sdk+adt+android ndk。其中前三者为基本的android开发环境需要的套件,ndk为生成动态库需要的交叉编译工具。
  在使用前需要提前配置好相关的环境变量:如ANDROID_SDK_HOME。除了JDK不用配置也可以在eclipse中配置好也能使用。
  下面假定已经安装好android_sdk,android_ndk,adt插件相关套件,并能够在eclipse中创建一个简单的helloworld示例项目运行起来。下面简单说明配置ndk开发环境。
  指定ndk: 首先在eclipse中指定ndk路径,依次点击菜单栏Windows->Preferences->Android->NDK,点击Browse选择本地的ndk路径:
在这里插入图片描述
   配置自动生成头文件: 这里使用eclipse的external tools自定义功能,依次点击Run->External Tools->External Tools Configurations,然后点击左边栏中的Program,选中后点击左上角的白色文件图标New launch configuration,创建的新的工具,然后转入Main选项卡填写相关的配置信息,我使用的基本配置如下:

NAME:  jni_h_header_generate
Location:  ${system_path:javah}
Working Directory:  ${workspace_loc:/mediatask}/jni
Arguments:  -classpath "${project_classpath};${env_var:ANDROID_SDK_HOME}/platforms/android-23/android.jar" ${java_type_name}

  以上配置皆可以按照需求修改,NAME即该工具的名称,随意修改;Location表示需要使用的命令的路径,这里使用的命令是javah,因为我配置了环境变量Path因此直接填写的${system_path:javah},也可以点击Browse两个选项卡选择,javah.exe的路径一般在%JAVA_HOME%/binWorking Directory即生成的JNI的头文件的路径,我这里填写的值表示在eclipse工作路径下的mediatask/jni路径下,当然也可以点击Browse指定具体的路径;Arguments即命令的参数,其中ANDROID_SDK_HOME也可以换成绝对路径,android-23可以换成自己的android版本。
在这里插入图片描述
在这里插入图片描述
  然后转向Refresh标签选中The project containing the seleced resource
在这里插入图片描述
  然后转向Common标签选中Display in favorites menu中的External Tools,表示在顶栏的工具栏中显示该工具:
在这里插入图片描述

3 生成JNI头文件

  首先保证有一个能够顺利运行的android项目。然后分别进行如下步骤:

  1. 选中项目右键Android Tools->Add Native Support,填入生成的native库的名称,点击Finish
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  2. 创建一个Java类,在该类中声明一个用native修饰的函数,该函数就是需要使用C/C++语言实现的方法,如public native void sayhello();也可以在MainActivity中添加该声明,如果只是测试JNI环境可以,正常开发环境下一般不建议;
  3. 在创建native方法的类中添加static { System.loadLibrary("hello");},需要添加到类中,其中的字符串为1步骤中的库名;
  4. 选中包含native方法的类,使用该才创建的external tools,我这里创建的是jni_h_header_generate生成对应的头文件;
    在这里插入图片描述
    在这里插入图片描述
  5. 在之前生成的hello.cpp中添加对应的实现,我这里使用的实现为如下,功能为在logcat中输出grayondream, hello,这里使用了android的log库,因此需要在Android.mk中添加LOCAL_LDLIBS += -llog
#include <jni.h>
#include <stdio.h>
#include <android/log.h>
#include "com_example_mediatask_MediaEncoder.h"

#define TAG "grayondream"
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)

JNIEXPORT void JNICALL Java_com_example_mediatask_MediaEncoder_sayhello
  (JNIEnv *, jobject)
{
    LOGV("grayondream, hello");
}
  1. 如果需要其他的库则在Android.mk中进行配置;
  2. 实现完成之后不要忘记在具体的代码中调用。
    在这里插入图片描述

4 可能遇到的问题

4.1 如果希望删除当前项目中的Native Support

   如果希望删除当前项目中的Native Support,则需要删除.cproject文件和修改.project文件,.project中需要删除如下内容。

		<buildCommand>
			<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
			<triggers>clean,full,incremental,</triggers>
			<arguments>
			</arguments>
		</buildCommand>

		<buildCommand>
			<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
			<triggers>full,incremental,</triggers>
			<arguments>
			</arguments>
		</buildCommand>

		<nature>org.eclipse.cdt.core.cnature</nature>
		<nature>org.eclipse.cdt.core.ccnature</nature>
		<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
		<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>

  如果删除之后出现JNI NDK错误 c/c++ indexer has encountered a problem, An internal error occurred during xx错误,则关闭eclipse,删除工作目录下.metadata\.plugins\org.eclipse.cdt.core中所有以.pdom为后缀的文件。

4.2 生成一次so之后频繁报File Exists的错误

  只需要在编译前将工程清空即可,按顺序点击Project->Clean

5 所有文件的内容

  源文件结构:

➜  mediatask ls .\src\com\example\mediatask\
Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           2021/3/20    22:47            445 MainActivity.java
-a---           2021/3/20    22:38            147 MediaEncoder.java

➜  mediatask ls .\jni\
Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           2021/3/20    22:45            169 Android.mk
-a---           2021/3/20    22:41            524 com_example_mediatask_MediaEncoder.h
-a---           2021/3/20    22:44            357 hello.cpp
//MainActivity.java
package com.example.mediatask;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import com.example.mediatask.*;
public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		MediaEncoder en = new MediaEncoder();
		en.sayhello();
	}
}

package com.example.mediatask;

public class MediaEncoder {
	static { 
		System.loadLibrary("hello");
	}
	public native void sayhello();
}

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_mediatask_MediaEncoder */

#ifndef _Included_com_example_mediatask_MediaEncoder
#define _Included_com_example_mediatask_MediaEncoder
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_mediatask_MediaEncoder
 * Method:    sayhello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_example_mediatask_MediaEncoder_sayhello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

#include <jni.h>
#include <stdio.h>
#include <android/log.h>
#include "com_example_mediatask_MediaEncoder.h"

#define TAG "grayondream"
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)

JNIEXPORT void JNICALL Java_com_example_mediatask_MediaEncoder_sayhello
  (JNIEnv *, jobject)
{
    LOGV("grayondream, hello");
}

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello
LOCAL_SRC_FILES := hello.cpp
LOCAL_LDLIBS += -llog
include $(BUILD_SHARED_LIBRARY)

6 参考

基于eclipse进行ndk开发的环境配置
Android之JNI NDK错误 c/c++ indexer has encountered a problem, An internal error occurred during xx
NDK项目添加和删除Native Support

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值