Android ndk开发

前言:我对C/C++是没有任何基础的,虽然大学中学了一个学期的C但是都算还给老师了。这篇文章是我做一个NDK项目积累下来的知识,可以说是一篇小白上手文章,所以高手请自行绕路。

1、准备

做NDK开发是非常要注意开发环境和开发版本的(个人认为)。我使用的是Eclipse (Luna 4.4.0),NDK版本r10,应该是在<=r6版本的NDK还需要安装cygwin(这这里就不讨论,网上大把资料),附上NDK的下载链接方便不能翻墙的朋友,32位 ,64位,网站不能访问,但是直接用下载链接是可以下载到的。

安装好NDK后,就需要在Eclipse上进行配置了。

1、windows-preferences-android-ndk-ndklocation  选择ndk的安装目录

2、配置builder环境在需要进行ndk开发的项目上右键-properties-builder-new - program 在出现的弹窗中做以下配置

3、右键项目工程Android tools - Add Native Support

出现jni目录以及Android.mk,xx.cpp就说明添加成功了。就可以进行NDK开发了。

2、Java调用C++中的方法。

例如:获取从C++文件中获取字符串并打印

在Activity类A中:

static{
    System.loadLibrary("xx");//xx是Android.mk文件中LOCAL_MODULE 的字段
}
//必须和ndk中的方法名一样
public native String getString();

//onclick方法
public void click(View v){
    String str = getString();
    System.out.println("调用JNI中的方法:"+str);
}

在ndk.cpp中

#include <jni.h>
#include<string.h>
/**
* extern "C" 是必须加的,经测试不加的话方法调用不成功,也没找到答案,有知道为什么的请* 告知,方法名称必须按照JNI的规范来Java_包名_类名_方法名,都必须以‘_‘隔开。
*/
extern "C" jstring Java_com_test_ndk_A_getString(JNIEnv* env,jobject thiz){
    jstring str ;
    //在C中的是以(*env)->调用的,网上大部分的博客文档也是这种情况。
    str = env->newStringUTF("hello world");//不能使用中文,不然会报错。
    return str;
}

运行工程即可看到效果。

3、C++中调用Java方法

在ClassB中

static{
    System.loadLibrary("ndk");
}
public native void loadJavaMethod();

public void f1(){
    String str ;
    str = "hello world from java";
    System.out.println(str);
}

public String f2(){
    String str ;
    str = "f2: hello world from java";
    System.out.println(str);
    return str;
}

public void f3(String str,int i){
    System.out.println("f3 内容为:"+str+",数字为:"+i);
}

在ndk.cpp中

#include <jni.h>
#include<string.h>
extern "C" void Java_com_test_ndk_B_loadJavaMethod(JNIEnv *env,jobject thiz){

    //调用无参无返回值的方法
    jclass cls = env->GetObjectClass(thiz);
    //GetMethodID("jclass对象","方法名","方法参数")
    jmethodID mID = env->GetMethodID(cls,"f1","()V");
    if(mID != NULL){
	 env->CallVoidMethod(thiz,mID);
    }
    //调用有参无返回值得方法
     //参数类型除了基本数据类型外,其他的都需要按照这样的格式
     //L包名/类名;  包名用/分割,必须以;结束
     //详情请参考这篇文章     
     jclass cls = env->GetObjectClass(thiz);
    jmethodID mID = env->GetMethodID(cls,"f3","(Ljava/lang/String;I)V");
    jstring content = env->NewStringUTF("hehe");
    jint i = 10;
    if(mID != NULL){
	 env->CallVoidMethod(thiz,mID,content,i);
    }
    //调用有返回值无参的方法
    jclass cls = env->GetObjectClass(thiz);
    jmethodID mID = env->GetMethodID(cls,"f2","()Ljava/lang/String;");
     if(mID != NULL){
	 env->CallObjectMethod(thiz,mID);
    }
    //调用其他类中的方法假设有一个Student类,如果要使用Student类中的内部类A,格式为
    //com/test/ndk/Student$A
    jclass stu = env->FindClass("com/test/ndk/Student");
    //实例化无参构造方法
    jobject stuObj = env->NewObject(stu,env->GetMethodID(stu,"<init>","()V"));
    jmethodID getNameId = env->GetMethodID(stu,"getName","()V");
    if(getNameId !=NULL){
	env->CallVoidMethod(stuObj,getNameId);
    }
}

4、在自己的 so文件中调用第三方的so文件

这种情况一般是因为第三方的C/C++中的方法不是按照JNI的规范来写,这时就需要进行重新包装,并使用,当然前提是有了第三方的说明文档。

将第三方的so文件配置到预编译环境

在工程的jni文件下新建prebuilt文件夹(名称随意)将第三方的so文件放到里面例如libthird.so,然后在这个文件夹下新建Androdid.mk文件,文件内容为

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := libthird
LOCAL_SRC_FILES := libthird.so

include $(PREBUILT_SHARED_LIBRARY)

打开jni下的Android.mk文件,加入以下字段

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := ndk
LOCAL_SRC_FILES := ndk.cpp

#名称和第三方mk中LOCAL_MODULE定义的名称一样
LOCAL_SHARED_LIBRARIES := libthird

include $(BUILD_SHARED_LIBRARY)

#添加路径
include $(LOCAL_PATH)/prebuilt/Android.mk

配置完成后,在工程的libs\armeabi目录下可以看到第三方的so文件,注意不能直接将第三方的so文件放到这个目录下。否则在builde的时候会删除。

假设在第三方的C/C++文件中有这样一个方法

//extern "C"在第三方的包中的方法也必须添加,测试时,如果不添加方法调用不成功,但这个是不能限//制到第三方的,有待解决
extern "C" int f1(){
	return 101;
}

在自己的C/C++文件中调用第三方的方法

#include <jni.h>
#include <dlfcn.h>
#include <fcntl.h>
void *filehandle = NULL;
jstring (*f1)() =NULL;
extern "C" jint Java_com_test_ndk_classA_f1(JNIEnv * env,jobject thiz){
    jint i ;
    filehandle = dlopen("/data/data/com.fly.ndk2/lib/libndk.so", RTLD_LAZY);
    if(filehandle){
	f1 = (int(*)())dlsym(filehandle,"f1");
    }
    if(f1){
        i = f1();
        dlclose(filehandle);
	filehandle = NULL;
    }
    return i;
}

以上内容除了没有涉及到真正的C/C++编程外,JNI开发的一些知识点都涉及到了,仅属入门的一些知识,在完全不了解C/C++编程的情况下耗费了2天时间才积累了以上知识。如果还需要更深入的学习就需要学习C/C++的语法知识以及编译。

以上的代码以及操作不一定在其他的环境中有效,谨记。

时间: 2024-12-19 12:43:47

Android ndk开发的相关文章

Android NDK开发篇(五):Java与原生代码通信(数据操作)

尽管说使用NDK能够提高Android程序的运行效率,可是调用起来还是略微有点麻烦.NDK能够直接使用Java的原生数据类型,而引用类型,由于Java的引用类型的实如今NDK被屏蔽了,所以在NDK使用Java的引用类型则要做对应的处理. 一.对引用数据类型的操作 尽管Java的引用类型的实如今NDK被屏蔽了,JNI还是提供了一组API,通过JNIEnv接口指针提供原生方法改动和使用Java的引用类型. 1.字符串操作 JNI把Java的字符串当作引用来处理,在NDK中使用Java的字符串,须要相

Android NDK 开发(三)--常见错误锦集合Log的使用【转】

转载请注明出处:http://blog.csdn.net/allen315410/article/details/41826511  Android NDK开发经常因某些因素会出现一些意想不到的错误,很多时候调试这些错误的时候,显得比调试Java代码要复杂,一方面是导致错误的原因很多很杂,另一方面NDK开发涉及到C/C++代码的编写,很多程序员对此不熟悉.那么这篇博客就总结一下,在NDK开发中经常出现的一些问题,并且尝试提供一些正确的解决方案,方便在开发时能够快速定位到错误,更改错误,当然了,错

Android NDK 开发

NDK全称:Native Development Kit. 1.NDK是一系列工具的集合. * NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk.这些工具对开发者的帮助是巨大的. * NDK集成了交叉编译器,并提供了相应的mk文件隔离平台.CPU.API等差异,开发人员只需要简单修改mk文件(指出"哪些文件需要编译"."编译特性要求"等),就可以创建出so. * NDK可以自动地将so和Java应用一起

C++开发安卓、windows下搭建Android NDK开发环境

1. NDK(Native Development Kit) 1.1 NDK简介 Android NDK是一套允许开发人员使用本地代码(如C/C++)进行Android APP功能开发的工具,通过这个工具,我们可以把用C/C++代码编译成可以直接运行在Android平台上的本地代码,这些本地代码以动态链接库( *.so )的形式存在,也正因为这样,我们可以通过复用这些动态链接库从而复用本地代码. 那么,通过NDK这个开发工具包,那么我们是否可以将一个APK完全使用C/C++来编写呢? 答案是不可

Android NDK 开发(四)java传递数据到C【转】

转载请注明出处:http://blog.csdn.net/allen315410/article/details/41845701 前面几篇文章介绍了Android NDK开发的简单概念.常见错误及处理和从第一个Hello World开始实际做一个简单的JNI开发示例,相信看完之后,大家对NDK开发有了一个概念上的认识了,那么接下来我们需要再深入一下NDK的开发,我们知道NDK开发就是使用JNI这层“协议”在Java和C之间起个“桥梁”的作用,将Java和Native C之间联立起来,让Java

跟我学Android NDK开发(一)

Android NDK 开发跟其它开发一样,首先需要配置好开发环境,本文以 Ubuntu系统为例介绍如何进行 Android NDK 开发环境的配置. 1. 简介 什么是 Android NDK 呢? NDK(Native Development Kit) 是一个允许开发者用一些本地语言(C/C++)编写 Android App 的部分功能的工具集.对于一些特定的 App,NDK 非常有利于我们直接使用现成的用 C/C++ 编写的代码库(但对于大多数 App 来说,NDK 是没有必要的).使用

Android NDK开发(八)——应用监听自身卸载,弹出用户反馈调查

转载请注明出处:http://blog.csdn.net/allen315410/article/details/42521251 监听卸载情景和原理分析 1,情景分析 在上上篇博客中我写了一下NDK开发实践项目,使用开源的LAME库转码MP3,作为前面几篇基础博客的加深理解使用的,但是这样的项目用处不大,除了练练NDK功底.这篇博客,我将讲述一下一个各大应用中很常见的一个功能,同样也是基于JNI开发的Android应用小Demo,看完这个之后,不仅可以加深对NDK开发的理解,而且该Demo也可

Android NDK开发常见错误

错误一: make: *** No rule to make target `/cygdrive/d/1-workspace/showmap-android-opengles/jni/showmap_opengles_OpenGLESRenderer.c', needed by `/cygdrive/d/1-workspace/showmap-android-opengles/obj/local/armeabi/objs/OpenGLESMap/showmap_opengles_OpenGLES

Android NDK开发(二)——从Hello World学起

转载请注明出处:http://blog.csdn.net/allen315410/article/details/41805719  上篇文章讲述了Android NDK开发的一些基本概念,以及NDK的环境搭建,相信看过的朋友NDK开发环境搭建应该是没有问题了,还没有搭建或者不知道怎么搭建的朋友请点击这里.那么这篇文章,我们跟刚学Java编程语言一样,从世界知名程序"Hello World!"开始,开发出我们的第一个NDK程序. NDK目录简单介绍 在进行NDK开发之前,我们有必须熟悉

Android ndk开发swig编译jni接口配置文件(二)

之前写过一篇Android ndk开发swig编译jni接口.看这篇看不懂,看以去看看.c++与Java有些语言结构还是有一定区别,比如c++结构体,一些函数的返回值等都是有所不同,进行swig编译要进行一些预处理,也就是配置一下就行.下面说说几种情况. 一.一般情况下string,数组,枚举类型等配置Unix.i %module Survey %include "std_string.i" %include "arrays_java.i" %include &qu