当前位置: 首页 > news >正文

桂林网站制作公司做马来西亚生意的网站

桂林网站制作公司,做马来西亚生意的网站,店铺装修效果图大全,网站开发 python 工具转载#xff1a;http://blog.csdn.net/zeng622peng/article/details/6675666 首先说明#xff0c;Android系统不允许一个纯粹使用C/C的程序出现#xff0c;它要求必须是通过Java代码嵌入Native C/C——即通过JNI的方式来使用本地#xff08;Native#xff09;代码。因此J…转载http://blog.csdn.net/zeng622peng/article/details/6675666 首先说明Android系统不允许一个纯粹使用C/C的程序出现它要求必须是通过Java代码嵌入Native C/C——即通过JNI的方式来使用本地Native代码。因此JNI对Android底层开发人员非常重要。 如何将.so文件打包到.APK 让我们 先 从最简单的情况开始假如已有一个JNI实现——libxxx.so文件那么如何在APK中使用它呢 在我最初写类似程序的时候我会将libxxx.so文件push到/system/lib/目录下然后在Java代码中执行System.loadLibrary(xxx)这是个可行的做法但需要取得/system/lib 目录 的写权限模拟器通过adb remount取得该权限。但模拟器 重启之 后libxxx.so文件会消失。现在 我找到了更好的方法把.so文件打包到apk中分发给最终用户不管是模拟器 或者 真机 都不再需要system分区的写权限。实现步骤如下 1、在你的项目根目录下建立libs/armeabi目录 2、将libxxx.so文件copy到 libs/armeabi/下 3、此时ADT插件自动编译输出的.apk文件中已经包括.so文件了 4、安装APK文件即可直接使用JNI中的方法 我想还需要简单说明一下libxxx.so的命名规则沿袭Linux传统libsomething.so是类库文件名称的格式但在Java的System.loadLibrary(“ something ”)方法中指定库名称时不能包括 前缀—— lib以及后缀——.so。 准备编写自己的JNI模块 你一定想知道如何编写自己的xxx.so不过这涉及了太多有关JNI的知识。简单的说JNI是Java平台定义的用于和宿主平台上的本地代码进行交互的“Java标准”它通常有两个使用场景1.使用(之前使用c/c、delphi开发的)遗留代码2.为了更好、更直接地与硬件交互并 获得更高性能 。你可以通过以下链接了解JNI的更多资料 Java Native Interface Developer Guides Java Native Interface Specification Java本地接口(JNI)基本功能 BookJNI Programmer’s Guide and Specification JNI之Hello World 1、首先创建含有native方法的Java类 package com.okwap.testjni; public final class MyJNI { //native方法, public static native String sayHello(String name); } package com.okwap.testjni; public final class MyJNI { //native方法, public static native String sayHello(String name); } 2、通过javah命令生成.h文件内容如下(com_okwap_testjni.h文件) /* DO NOT EDIT THIS FILE - it is machine generated */ #include JNI.H /* Header for class com_okwap_testjni_MyJNI */ #ifndef _Included_com_okwap_testjni_MyJNI #define _Included_com_okwap_testjni_MyJNI #ifdef __cplusplus extern C { #endif /* * Class: com_okwap_testjni_MyJNI * Method: sayHello * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_okwap_testjni_MyJNI_sayHello (JNIEnv *, jclass, jstring); #ifdef __cplusplus } #endif #endif /* DO NOT EDIT THIS FILE - it is machine generated */ #include jni.h /* Header for class com_okwap_testjni_MyJNI */ #ifndef _Included_com_okwap_testjni_MyJNI #define _Included_com_okwap_testjni_MyJNI #ifdef __cplusplus extern C { #endif /* * Class: com_okwap_testjni_MyJNI * Method: sayHello * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_okwap_testjni_MyJNI_sayHello (JNIEnv *, jclass, jstring); #ifdef __cplusplus } #endif #endif /jni.h 这是一个标准的C语言头文件其中的JNIEXPORT、JNICALL是JNI关键字(事实上它是没有任何内容的宏仅用于指示性说明)而jint、jstring是JNI环境下对int及java.lang.String类型的映射。这些关键字的定义都可以在jni.h中看到。3、在 com_okwap_testjni.c文件中实现以上方法#include STRING.H #include JNI.H #include com_okwap_testjni.h JNIEXPORT jstring JNICALL Java_com_okwap_testjni_MyJNI_sayHello(JNIEnv* env, jclass, jstring str){ //从jstring类型取得c语言环境下的char*类型 const char* name (*env)-GetStringUTFChars(env, str, 0); //本地常量字符串 char* hello 你好; //动态分配目标字符串空间 char* result malloc((strlen(name) strlen(hello) 1)*sizeof(char)); memset(result,0,sizeof(result)); //字符串链接 strcat(result,hello); strcat(result,name); //释放jni分配的内存 (*env)-ReleaseStringUTFChars(env,str,name); //生成返回值对象 str (*env)-NewStringUTF(env, 你好 JNI~!); //释放动态分配的内存 free(result); // return str; } #include string.h #include jni.h #include com_okwap_testjni.h JNIEXPORT jstring JNICALL Java_com_okwap_testjni_MyJNI_sayHello(JNIEnv* env, jclass, jstring str){ //从jstring类型取得c语言环境下的char*类型 const char* name (*env)-GetStringUTFChars(env, str, 0); //本地常量字符串 char* hello 你好; //动态分配目标字符串空间 char* result malloc((strlen(name) strlen(hello) 1)*sizeof(char)); memset(result,0,sizeof(result)); //字符串链接 strcat(result,hello); strcat(result,name); //释放jni分配的内存 (*env)-ReleaseStringUTFChars(env,str,name); //生成返回值对象 str (*env)-NewStringUTF(env, 你好 JNI~!); //释放动态分配的内存 free(result); // return str; } /jni.h/string.h 4、编译——两种不同的编译环境以上的C语言代码要编译成最终.so动态库文件有两种途径Android NDK 全称是Native Developer Kit是用于编译本地JNI源码的工具为开发人员将本地方法整合到Android应用中提供了方便。事实上NDK和完整源码编译环境一样都使用Android的编译系统——即通过Android.mk文件控制编译。NDK可以运行在Linux、Mac、Window(cygwin)三个平台上。有关NDK的使用方法及更多细节请参考以下资料eoe特刊第七期《NDK总结》http://blog.eoemobile.com/?p27http://androidappdocs.appspot.com/sdk/ndk/index.html 完整源码编译环境 Android平台提供有基于make的编译系统为App编写正确的Android.mk文件就可使用该编译系统。该环境需要通过git从官方网站获取完整源码副本并成功编译更多细节请参考http://source.android.com/index.html不管你选择以上两种方法的哪一个都必须编写自己的Android.mk文件有关该文件的编写请参考相关文档。JNI组件的入口函数——JNI_OnLoad()、JNI_OnUnload()JNI组件被成功加载和卸载时会进行函数回调当VM执行到System.loadLibrary(xxx)函数时首先会去执行JNI组件中的JNI_OnLoad()函数而当VM释放该组件时会呼叫JNI_OnUnload()函数。先看示例代码//onLoad方法在System.loadLibrary()执行时被调用 jint JNI_OnLoad(JavaVM* vm, void* reserved){ LOGI(JNI_OnLoad startup~~!); return JNI_VERSION_1_4; } //onUnLoad方法在JNI组件被释放时调用 void JNI_OnUnload(JavaVM* vm, void* reserved){ LOGE(call JNI_OnUnload ~~!!); } //onLoad方法在System.loadLibrary()执行时被调用 jint JNI_OnLoad(JavaVM* vm, void* reserved){ LOGI(JNI_OnLoad startup~~!); return JNI_VERSION_1_4; } //onUnLoad方法在JNI组件被释放时调用 void JNI_OnUnload(JavaVM* vm, void* reserved){ LOGE(call JNI_OnUnload ~~!!); } JNI_OnLoad()有两个重要的作用指定JNI版本告诉VM该组件使用那一个JNI版本(若未提供JNI_OnLoad()函数VM会默认该使用最老的JNI 1.1版)如果要使用新版本的JNI例如JNI 1.4版则必须由JNI_OnLoad()函数返回常量JNI_VERSION_1_4(该常量定义在jni.h中) 来告知VM。初始化设定当VM执行到System.loadLibrary()函数时会立即先呼叫JNI_OnLoad()方法因此在该方法中进行各种资源的初始化操作最为恰当。JNI_OnUnload()的作用与JNI_OnLoad()对应当VM释放JNI组件时会呼叫它因此在该方法中进行善后清理资源释放的动作最为合适。使用registerNativeMethods方法对Java程序员来说可能我们总是会遵循1.编写带有native方法的Java类—2.使用javah命令生成.h头文件—3.编写代码实现头文件中的方法这样的“官方” 流程但也许有人无法忍受那“丑陋”的方法名称RegisterNatives方法能帮助你把c/c中的方法隐射到Java中的native方法而无需遵循特定的方法命名格式。来看一段示例代码吧//定义目标类名称 static const char *className com/okwap/testjni/MyJNI; //定义方法隐射关系 static JNINativeMethod methods[] { {sayHello, (Ljava/lang/String;)Ljava/lang/String;, (void*)sayHello}, }; jint JNI_OnLoad(JavaVM* vm, void* reserved){ //声明变量 jint result JNI_ERR; JNIEnv* env NULL; jclass clazz; int methodsLenght; //获取JNI环境对象 if ((*vm)-GetEnv(vm, (void**) env, JNI_VERSION_1_4) ! JNI_OK) { LOGE(ERROR: GetEnv failed\n); return JNI_ERR; } assert(env ! NULL); //注册本地方法.Load 目标类 clazz (*env)-FindClass(env,className); if (clazz NULL) { LOGE(Native registration unable to find class %s, className); return JNI_ERR; } //建立方法隐射关系 //取得方法长度 methodsLenght sizeof(methods) / sizeof(methods[0]); if ((*env)-RegisterNatives(env,clazz, methods, methodsLenght) 0) { LOGE(RegisterNatives failed for %s, className); return JNI_ERR; } // result JNI_VERSION_1_4; return result; } //定义目标类名称 static const char *className com/okwap/testjni/MyJNI; //定义方法隐射关系 static JNINativeMethod methods[] { {sayHello, (Ljava/lang/String;)Ljava/lang/String;, (void*)sayHello}, }; jint JNI_OnLoad(JavaVM* vm, void* reserved){ //声明变量 jint result JNI_ERR; JNIEnv* env NULL; jclass clazz; int methodsLenght; //获取JNI环境对象 if ((*vm)-GetEnv(vm, (void**) env, JNI_VERSION_1_4) ! JNI_OK) { LOGE(ERROR: GetEnv failed\n); return JNI_ERR; } assert(env ! NULL); //注册本地方法.Load 目标类 clazz (*env)-FindClass(env,className); if (clazz NULL) { LOGE(Native registration unable to find class %s, className); return JNI_ERR; } //建立方法隐射关系 //取得方法长度 methodsLenght sizeof(methods) / sizeof(methods[0]); if ((*env)-RegisterNatives(env,clazz, methods, methodsLenght) 0) { LOGE(RegisterNatives failed for %s, className); return JNI_ERR; } // result JNI_VERSION_1_4; return result; }建立c/c方法和Java方法之间映射关系的关键是 JNINativeMethod 结构该结构定义在jni.h中具体定义如下typedef struct { const char* name;//java方法名称 const char* signature; //java方法签名 void* fnPtr;//c/c的函数指针 } JNINativeMethod; typedef struct { const char* name;//java方法名称 const char* signature; //java方法签名 void* fnPtr;//c/c的函数指针 } JNINativeMethod; 参照上文示例中初始化该结构的代码//定义方法隐射关系 static JNINativeMethod methods[] { {sayHello, (Ljava/lang/String;)Ljava/lang/String;, (void*)sayHello}, }; //定义方法隐射关系 static JNINativeMethod methods[] { {sayHello, (Ljava/lang/String;)Ljava/lang/String;, (void*)sayHello}, }; 其中比较难以理解的是第二个参数——signature字段的取值实际上这些字符与函数的参数类型/返回类型一一对应其中() 中的字符表示参数后面的则代表返回值。例如()V 就表示void func()(II)V 表示 void func(int, int)具体的每一个字符的对应关系如下字符 Java类型 C/C类型V void voidZ jboolean booleanI jint intJ jlong longD jdouble doubleF jfloat floatB jbyte byteC jchar charS jshort short数组则以[开始用两个字符表示字符 java类型 c/c类型[Z jbooleanArray boolean[][I jintArray int[][F jfloatArray float[][B jbyteArray byte[][C jcharArray char[][S jshortArray short[][D jdoubleArray double[][J jlongArray long[]上面的都是基本类型如果参数是Java类则以L开头以;结尾中间是用/隔开包及类名而其对应的C函数的参数则为jobject一个例外是String类它对应C类型jstring例如Ljava/lang /String; 、Ljava/net/Socket; 等如果JAVA函数位于一个嵌入类也被称为内部类则用$作为类名间的分隔符例如Landroid/os/FileUtils$FileStatus;。使用registerNativeMethods方法不仅仅是为了改变那丑陋的长方法名最重要的是可以提高效率因为当Java类别透过VM呼叫到本地函数时通常是依靠VM去动态寻找.so中的本地函数(因此它们才需要特定规则的命名格式)如果某方法需要连续呼叫很多次则每次都要寻找一遍所以使用RegisterNatives将本地函数向VM进行登记可以让其更有效率的找到函数。registerNativeMethods方法的另一个重要用途是运行时动态调整本地函数与Java函数值之间的映射关系只需要多次调用registerNativeMethods()方法并传入不同的映射表参数即可。JNI中的日志输出你一定非常熟悉在Java代码中使用Log.x(TAG,“message”)系列方法在c/c代码中也一样不过首先你要include相关头文件。遗憾的是你使用不同的编译环境( 请参考上文中两种编译环境的介绍) 对应的头文件略有不同。。如果是在完整源码编译环境下只要include 头文件就可以使用对应的LOGI、LOGD等方法了同时请定义LOG_TAGLOG_NDEBUG等宏值示例代码如下#define LOG_TAG HelloJni #define LOG_NDEBUG 0 #define LOG_NIDEBUG 0 #define LOG_NDDEBUG 0 #include STRING.H #include JNI.H #include UTILS Log.h jstring Java_com_inc_android_ime_HelloJni_stringFromJNI(JNIEnv* env,jobject thiz){ LOGI(Call stringFromJNI!\n); return (*env)-NewStringUTF(env, Hello from JNI 中文!); } #define LOG_TAG HelloJni #define LOG_NDEBUG 0 #define LOG_NIDEBUG 0 #define LOG_NDDEBUG 0 #include string.h #include jni.h #include utils log jstring Java_com_inc_android_ime_HelloJni_stringFromJNI(JNIEnv* env,jobject thiz){ LOGI(Call stringFromJNI!\n); return (*env)-NewStringUTF(env, Hello from JNI 中文!); } /utils/jni.h/string.h 与日志相关的.h头文件在以下源码路径myeclair\frameworks\base\include\utils\Log.hmyeclair\system\core\include\cutils\log.h如果你是在NDK环境下编译则需要#include 示例代码如下#define LOG_TAG HelloJni #include STRING.H #include JNI.H #include UTILS Log.h jstring Java_com_inc_android_ime_HelloJni_stringFromJNI(JNIEnv* env,jobject thiz){ __android_log_print(ANDROID_LOG_INFO,LOG_TAG,Call stringFromJNI!\n); return (*env)-NewStringUTF(env, Hello from JNI 中文!); } #define LOG_TAG HelloJni #include string.h #include jni.h #include utils log jstring Java_com_inc_android_ime_HelloJni_stringFromJNI(JNIEnv* env,jobject thiz){ __android_log_print(ANDROID_LOG_INFO,LOG_TAG,Call stringFromJNI!\n); return (*env)-NewStringUTF(env, Hello from JNI 中文!); } /utils/jni.h/string.h 很可惜其中用于日志输出的方法是 __android_log_print(....) 并不是我们熟悉的LOG.x(...)系列方法。不过好的一点是android/log.h文件在完整源码环境下也是可用的因此可以用一下的头文件来统两种环境下的差异/* * jnilogger.h * * Created on: 2010-11-15 * Author: INC062805 */ #ifndef __JNILOGGER_H_ #define __JNILOGGER_H_ #include ANDROID log.h #ifdef _cplusplus extern C { #endif #ifndef LOG_TAG #define LOG_TAG MY_LOG_TAG #endif #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__) #ifdef __cplusplus } #endif #endif /* __JNILOGGER_H_ */ /* * jnilogger.h * * Created on: 2010-11-15 * Author: INC062805 */ #ifndef __JNILOGGER_H_ #define __JNILOGGER_H_ #include android log #ifdef _cplusplus extern C { #endif #ifndef LOG_TAG #define LOG_TAG MY_LOG_TAG #endif #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__) #ifdef __cplusplus } #endif #endif /* __JNILOGGER_H_ */ /android 你可以下载以上头文件来统一两种不同环境下的使用差异。另外不要忘了在你的Android.mk文件中加入对类库的应用两种环境下分别是 ifeq ($(HOST_OS),windows) #NDK环境下 LOCAL_LDLIBS : -llog else #完整源码环境下 LOCAL_SHARED_LIBRARIES : libutils endif ifeq ($(HOST_OS),windows) #NDK环境下 LOCAL_LDLIBS : -llog else #完整源码环境下 LOCAL_SHARED_LIBRARIES : libutils endif Android为JNI提供的助手方法myeclair\dalvik\libnativehelper\include\nativehelper在完整源码编译环境下Android在myeclair\dalvik\libnativehelper\include\nativehelper\JNIHelp.h头文件中 提供了助手函数 用于本地方法注册、异常处理等任务还有一个用于计算方法隐射表长度的宏定义#ifndef NELEM # define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) #endif //有了以上宏定义后注册方法可以按如下写该宏定义可以直接copy到NDK环境下使用 (*env)-RegisterNatives(env,clazz, methods,NELEM(methods)); #ifndef NELEM # define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) #endif //有了以上宏定义后注册方法可以按如下写该宏定义可以直接copy到NDK环境下使用 (*env)-RegisterNatives(env,clazz, methods,NELEM(methods));
http://www.pierceye.com/news/155656/

相关文章:

  • 广东省建设教育协会官方网站首页世界上最有趣的网站
  • 平面构成作品网站手机网页qq登录
  • 厦门app开发网站开发公司电话重庆网站排名外包
  • 个人备案经营网站用自己网站做邮箱域名解析
  • 为什么大公司开发网站做英文网站网站犯法吗
  • 大连网站seo陇西网站建设公司
  • 电力建设工程质监总站网站域名使用费用一年多少钱
  • 建设单位网站经费请示上海外国语大学学风建设网站
  • 优秀网站管理员wordpress淘宝客模板下载
  • 广州越秀区网站建设手工制作简单又漂亮
  • 西安商城网站开发网站建设前台后台教程
  • 网站投放天津塘沽爆炸事件
  • 360网站安全检测自己买个服务器做网站
  • 临汾市网站建设网站版式分类
  • 广东的一起(17)做网站东莞建工集团企业网站
  • 最佳外贸英文网站模板六安网站设计公司
  • 为啥网站打开速度慢备案域名怎么弄
  • 门户网站建设主要内容深圳网站有哪些
  • 最好看的免费网站源码龙泉驿最新消息
  • 百度建立网站需要花多少钱学校门户网站建设工作
  • 网站安全防护方案沈阳网站建设策划方案
  • php做网站需要啥技术网站每年空间域名费用及维护费
  • 商城网站建设报个人免费网站
  • 公司网站开发建设wordpress首页加图片
  • 个人网站怎么写建设工程网站广州
  • 东阿网站制作如何在国外网站做推广
  • 宣城公司做网站潍坊市住房和城乡建设局网站
  • 用自己服务器做网站用备案wordpress弹窗订阅
  • 配色相关网站省住房城乡建设厅网站
  • 做汽车配件出口用什么网站好些求百度关键词搜索网站