热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入探索NDK与JNI技术的实践应用与学习路径

本文深入探讨了NDK与JNI技术在实际项目中的应用及其学习路径。通过分析工程目录结构和关键代码示例,详细介绍了如何在Android开发中高效利用NDK和JNI,实现高性能计算和跨平台功能。同时,文章还提供了从基础概念到高级实践的系统学习指南,帮助开发者快速掌握这些关键技术。

工程的目录结构如下:


public class MainActivity extends Activity {/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);String[] argv=new String[]{"mylib","Gao","GaoMatrix"};Natives.libMain(argv);}
}

/*** @author GaoMatrix E-mail:gcquan08@gmail.com* @version Time:2011-8-20*/
public class Natives {static{System.loadLibrary("mylib");}public static native int libMain(String[] argv);private static void onMessage(String text,int level){// System.out.println("Message:"+text+" Level:"+level);Log.d("JNI", "Message:"+text+" Level:"+level);}
}

Android.mk:

LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:=mylib
LOCAL_SRC_FILES:=mylib.c
LOCAL_LDLIBS := -llog
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -lloginclude $(BUILD_SHARED_LIBRARY)

include/Natives.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class Natives */#ifndef _Included_Natives
#define _Included_Natives
#ifdef __cplusplus
extern "C" {
#endif
/** Class: Natives* Method: libMain* Signature: ([Ljava/lang/String;)I*/
JNIEXPORT jint JNICALL Java_com_gao_Natives_libMain(JNIEnv *, jclass, jobjectArray);#ifdef __cplusplus
}
#endif
#endif
mylib.c:

#include
#include
#include
#include "include/Natives.h"#include
#define LOG_TAG "JNI"
#define LOGD(a) __android_log_write(ANDROID_LOG_DEBUG,LOG_TAG,a)#define CB_CLASS "com/gao/Natives"/**
* onMessage callback
*/
#define CB_CLASS_MSG_CB "onMessage"
#define CB_CLASS_MSG_SIG "(Ljava/lang/String;I)V"//lib main sub
int lib_main(int argc,char **argv);//Used to get the len of a java Array
const int getArrayLen(JNIEnv* env,jobjectArray jarray);//print str message back to java
void jni_printf(char* format,...);//Global env ref(for callback)
static JavaVM* g_VM;//Global Reference to the native java calss com.gao.Natives.java
static jclass jNativesCls;JNIEXPORT jint JNICALL Java_com_gao_Natives_libMain(JNIEnv *env, jclass cls, jobjectArray jarray)
{//obtain a global ref to the caller class(*env)->GetJavaVM(env,&g_VM);//Extract char **args from java arrayjsize len=getArrayLen(env,jarray);char* args[(int)len];int i;jstring jrow;for(i=0;iGetObjectArrayElement(env,jarray,i);const char* row=(*env)->GetStringUTFChars(env,jrow,0);args[i]=malloc(strlen(row)+1);strcpy(args[i],row);//print argsjni_printf("Main argv[%d]=%s",i,args[i]);//LOGD("From C "+*args[i]);LOGD("From C ");//free java string jrow(*env)->ReleaseStringUTFChars(env,jrow,row);}//Load the com.gao.Natives classjNativesCls=(*env)->FindClass(env,CB_CLASS);if(jNativesCls==0){jni_printf("Unable to find class:%s",CB_CLASS);return -1;}//Invoke the lib main sub.This will loop forener//Program agrs com from Javalib_main(len,args);return 0;
}/**
*Send a string back to Java
*/
jmethodID mSendStr;
static void jni_send_str(const char* text,int level)
{JNIEnv* env;if(!g_VM){printf("I_JNI_NOVM:%s\n",text);return;}(*g_VM)->AttachCurrentThread(g_VM,(void **)&env,NULL);//Load jni.Natives if missingif(!jNativesCls){jNativesCls=(*env)->FindClass(env,CB_CLASS);if(jNativesCls==0){printf("Unable to find class:%s",CB_CLASS);return;}}//Call com.gao.Natives.onMessage(String,int)if(!mSendStr){//Get a ref to the static method:com.gao.Natives.onMessagemSendStr=(*env)->GetStaticMethodID(env,jNativesCls,CB_CLASS_MSG_CB,CB_CLASS_MSG_SIG);}if(mSendStr){(*env)->CallStaticVoidMethod(env,jNativesCls,mSendStr,(*env)->NewStringUTF(env,text),(jint)(level));}else{printf("Unable to find method: %s, signature: %s\n", CB_CLASS_MSG_CB, CB_CLASS_MSG_SIG );}}/**
*Get java array length
*/const int getArrayLen(JNIEnv* env,jobjectArray jarray)
{return (*env)->GetArrayLength(env,jarray);
}/*** Printf into the java layer* does a varargs printf into a temp buffer* and calls jni_sebd_str*/
void jni_printf(char* format,...)
{va_list argptr;static char string[1024];va_start(argptr,format);vsprintf(string,format,argptr);va_end(argptr);jni_send_str(string,0);
}/**
*Library main sub
*/
int lib_main(int argc,char** argv)
{int i;jni_printf("Entering LIB MAIN");for(i=0;i}
运行结果:

08-20 21:50:50.350: DEBUG/JNI(7574): Message:Main argv[0]=mylib Level:0
08-20 21:50:50.350: DEBUG/JNI(7574): From C
08-20 21:50:50.350: DEBUG/JNI(7574): Message:Main argv[1]=Gao Level:0
08-20 21:50:50.350: DEBUG/JNI(7574): From C
08-20 21:50:50.350: DEBUG/JNI(7574): Message:Main argv[2]=GaoMatrix Level:0
08-20 21:50:50.350: DEBUG/JNI(7574): From C
08-20 21:50:50.350: DEBUG/JNI(7574): Message:Entering LIB MAIN Level:0
08-20 21:50:50.350: DEBUG/JNI(7574): Message:Lib Main argv[0]=mylib Level:0
08-20 21:50:50.350: DEBUG/JNI(7574): Message:Lib Main argv[1]=Gao Level:0
08-20 21:50:50.350: DEBUG/JNI(7574): Message:Lib Main argv[2]=GaoMatrix Level:0


推荐阅读
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • 本文详细介绍了如何使用 Yii2 的 GridView 组件在列表页面实现数据的直接编辑功能。通过具体的代码示例和步骤,帮助开发者快速掌握这一实用技巧。 ... [详细]
  • Android 渐变圆环加载控件实现
    本文介绍了如何在 Android 中创建一个自定义的渐变圆环加载控件,该控件已在多个知名应用中使用。我们将详细探讨其工作原理和实现方法。 ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • 作为一名新手,您可能会在初次尝试使用Eclipse进行Struts开发时遇到一些挑战。本文将为您提供详细的指导和解决方案,帮助您克服常见的配置和操作难题。 ... [详细]
  • 本章将深入探讨移动 UI 设计的核心原则,帮助开发者构建简洁、高效且用户友好的界面。通过学习设计规则和用户体验优化技巧,您将能够创建出既美观又实用的移动应用。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 本文详细介绍了中央电视台电影频道的节目预告,并通过专业工具分析了其加载方式,确保用户能够获取最准确的电视节目信息。 ... [详细]
  • Android 九宫格布局详解及实现:人人网应用示例
    本文深入探讨了人人网Android应用中独特的九宫格布局设计,解析其背后的GridView实现原理,并提供详细的代码示例。这种布局方式不仅美观大方,而且在现代Android应用中较为少见,值得开发者借鉴。 ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 本文介绍了如何在C#中启动一个应用程序,并通过枚举窗口来获取其主窗口句柄。当使用Process类启动程序时,我们通常只能获得进程的句柄,而主窗口句柄可能为0。因此,我们需要使用API函数和回调机制来准确获取主窗口句柄。 ... [详细]
author-avatar
大叔丶你好哇塞
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有