androidjni源码
‘壹’ 如何在android源码中添加自己的jni方法
1,、项目实现了一个简单的四则运算,项目的目录层次如下:
AndroidManifest.xml Android.mk jni res src
资源文件简简单单,一个布局文件,稍后会有demo的下载地址
主要记录备忘的内容如下:
MainActivity.java
[html] view plain public native int add(int x, int y);
public native int substraction(int x, int y);
public native float multiplication(int x, int y);
public native float division(int x, int y);
static{
System.loadLibrary("arithmetic");
}
2、生成lib的名称为libarithmetic.so.注意load的时候写"arithmetic"
jni 目录下有两个文件,一个是Android.mk,一个是c++源文件long.cpp
jni/Android.mk如下:
[html] view plain LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= libarithmetic
LOCAL_SRC_FILES:= \
long.cpp
LOCAL_SHARED_LIBRARIES := \
libutils
LOCAL_STATIC_LIBRARIES :=
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE)
LOCAL_CFLAGS +=
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
3、注释:
LOCAL_PATH(必须定义,而且要第一个定义),宏函数‘my-dir’, 由编译系统提供,用于返回当前路径(即包含Android.mk
file文件的目录);
include $( CLEAR_VARS),
CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE为你清除许多LOCAL_XXX变量(例如 LOCAL_MODULE,
LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...),除LOCAL_PATH
。这是必要的,因为所有的编译控制文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的;
LOCAL_MODULE_TAGS :=user eng tests optional
user: 指该模块只在user版本下才编译
eng: 指该模块只在eng版本下才编译
tests: 指该模块只在tests版本下才编译
optional:指该模块在所有版本下都编译
LOCAL_MODULE(必须定义),标识你在Android.mk文件中描述的每个模块。名称必须是唯一的,而且不包含任何空格。Note:编译系统会自动产生合适的前缀和后缀,例如:arithmetic编译成功后将生成libarithmetic.so库文件
LOCAL_SRC_FILES 变量必须包含将要编译打包进模块中源代码文件。不用在这里列出头文件和包含文件。
LOCAL_SHARED_LIBRARIES中加入所需要链接的动态库(*.so)的名称
LOCAL_STATIC_LIBRARIES加入所需要链接的静态库(*.a)的名称
LOCAL_CFLAG可选的编译器选项,用法之一是定义宏,例如LOCAL_CFLAGS := -Werror作用是编译警告也作为错误信息
LOCAL_PRELINK_MODULE:=false,不作prelink处理,默认是要prelink操作的,有可能造成地址空间冲突(这地方目前还不明白)
long.cpp源代码如下:
[html] view plain #define LOG_TAG "LongTest2 long.cpp"
#include
#include
#include "jni.h"
jint add(JNIEnv *env, jobject thiz, jint x, jint y){
return x + y;
}
jint substraction(JNIEnv *env, jobject thiz, jint x, jint y){
return x - y;
}
jfloat multiplication(JNIEnv *env, jobject thiz, jint x, jint y){
return (float)x * (float)y;
}
jfloat division(JNIEnv *env, jobject thiz, jint x, jint y){
return (float)x/(float)y;
}
static const char *classPathName = "com/inspur/test2/MainActivity";
static JNINativeMethod methods[]= {
{"add", "(II)I", (void*)add},
{"substraction", "(II)I", (void*)substraction},
{"multiplication", "(II)F", (void*)multiplication},
{"division", "(II)F", (void*)division},
};
typedef union{
JNIEnv* env;
void* venv;
}UnionJNIEnvToVoid;
static int registerNativeMethods(JNIEnv* env, const char* className,
JNINativeMethod* gMethods, int numMethods){
jclass clazz;
clazz = env->FindClass(className);
if (clazz == NULL)
return JNI_FALSE;
if (env->RegisterNatives(clazz, gMethods, numMethods)<0)
return JNI_FALSE;
return JNI_TRUE;
}
static int registerNatives(JNIEnv *env){
if (!registerNativeMethods(env, classPathName,
methods, sizeof(methods)/sizeof(methods[0])))
{
return JNI_FALSE;
}
return JNI_TRUE;
}
jint JNI_OnLoad(JavaVM* vm, void* reserved){
UnionJNIEnvToVoid uenv;
uenv.venv = NULL;
jint result = -1;
JNIEnv *env = NULL;
if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK){
goto l;
}
env = uenv.env;
env = uenv.env;
if (registerNatives(env) != JNI_TRUE){
goto l;
}
result = JNI_VERSION_1_4;
l:
return result;
}
除了利用 编写native JAVA类,通过javah生成.h文件,根据.h文件编写.c/cpp文件
方法外(名字像老太太的裹脚步,又臭又长,而且不灵活),Android还可以通过引用JNI_Onload方式实现。jint JNI_onLoad(JavaVM*
vm, void* reverced),改方法在so文件被加载时调用。
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组件时会呼叫它,因此在该方法中进行善后清理,资源释放的动作最为合适。
4、项目根目录下Android.mk文件:
[html] view plain LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_JNI_SHARED_LIBRARIES := libarithmetic
LOCAL_PACKAGE_NAME := LongTest
LOCAL_SHARED_LIBRARIES := \
libutils\
liblog
include $(BUILD_PACKAGE)
include $(LOCAL_PATH)/jni/Android.mk
# Also build all of the sub-targets under this one: the shared library.
include $(call all-makefiles-under,$(LOCAL_PATH))
LOCAL_PACKAGE_NAME:项目名称,即最终生成apk的名字
LOCAL_JNI_SHARED_LIBRARIES := libxxx就是把so文件放到apk文件里的libs/armeabi里
执行BUILD_PACKAGE。它的定义也是在config.mk中定义如下:BUILD_PACKAGE:=
$(BUILD_SYSTEM)/package.mk
$(call all-java-files-under, src)编译的源代码文件列表添加src目录下所有的java 源文件
$(call all-makefiles-under, $(LOCAL_PATH))编译器会在编译完当前目录下的文件后再深入子目录编译
如果make过android源码,可以在项目根目录下执行mm命令进行编译。前提是执行过source
androidSRC/build/envsetup.sh
或者直接把source androidSRC/build/envsetup.sh添加到~/.bashrc中,会更加方便
‘贰’ Android源码学习之如何创建使用JNI
publicclassHelloWorld{
();//所有native关键词修饰的都是对本地的声明
static{
System.loadLibrary("hello");//载入本地库
}
publicstaticvoidmain(String[]args){
newHelloWorld().displayHelloWorld();
}
}
上面的就是使用JNI的方式,其中so库的名字是libhello.so,放到libs下面。
jni中的方法需要在修饰符后面加上native,
例如:();,
在使用之前需要导入so库,
导入方法:
static{
System.loadLibrary("hello");//载入本地库
}
在导入的时候是可以省略so库前面的lib的,当然加上也没事。
还有就是使用的地方一定要在固定的包名类名下。
希望能够帮助你。
‘叁’ 如何在Android下使用JNI
Android中JNI是编译so库的源代码,编译成功后会生成SO库,android中最终是使用SO库的。 1.android的NDK开发需要在linux下进行: 因为需要把C/C++编写的代码生成能在arm上运行的.so文件,这就需要用到交叉编译环境,而交叉编译需要在linux系统下才能完成。 2.安装android-ndk开发包,这个开发包可以在google android 官网下载: 通过这个开发包的工具才能将android jni 的C/C++的代码编译成库 3.android应用程序开发环境: 包括eclipse、java、 android sdk、 adt等。 NDK编译步骤: 1.选择 ndk 自带的例子 hello-jni ,我的位于E:\android-ndk-r5\samples\hello-jni( 根据具体的安装位置而定 ) 。 2.运行 cygwin ,输入命令 cd /cygdrive/e/android-ndk-r5/samples/hello-jni ,进入到 E:\android-ndk-r5\samples\hello-jni 目录。 3.输入 $NDK/ndk-build ,执行成功后,它会自动生成一个 libs 目录,把编译生成的 .so 文件放在里面。 ($NDK是调用我们之前配置好的环境变量, ndk-build 是调用 ndk 的编译程序 ) 4.此时去 hello-jni 的 libs 目录下看有没有生成的 .so 文件,如果有,ndk 就运行正常啦。
‘肆’ android studio 怎么编译jni
一、使用已经编译好的so
这种情况比较件简单,只要把的.so文件放到相应的目录即可。如下:
.[mole_name]
. . [src]
. . .[main]
. . . .[jniLibs]
. . . . .[armeabi]
. . . . .[armeabi-v7a]
. . . . .[x86]
. . . . .[mips]
注意 jniLibs 目录是放在 mole 下面,在Android Studio中效果如下,这样编译之后so就会被自动打包进apk,代码中直接 loadLibrary即可了:
1 String libName = "helloNDK"; // 库名, 注意没有前缀lib和后缀.so
2 System.loadLibrary( libName );
二、使用C/C++源码
1 r9d以上版本NDK
首先确保自己的NDK版本在r9d以上,目前最新可以拿到的是r10,下载地址:
http://tools.android-studio.org/
感谢 Android Studio中文组的无私奉献。
如果低于r9d版本,Android studio 下ndk编译会出现 No rule to make target 的错误。
2 配置 ndk.dir
在 local.properties 添加如下配置:
sdk.dir=/path/to/android-sdk
ndk.dir=/path/to/android-ndk
‘伍’ android 源码dvmusejnibridge在哪
一、下载android 源码 1/android/git-repo/git-repo' 改为清华大学的地址 REPO_URL = 'git://aosp/android/git-repo' 3/platform/manifest 改为清华大学的地址 $ repo init -u git://aosp/android/platform/manifest 4/" /> 改为下面的code即可: <remote name="aosp" fetch="git://aosp/android/" review="https://android-review/" /> 这个方法也可以用来在同步Cyanogenmod代码的时候从TUNA同步部分代码
‘陆’ android jni 使用第三方提供的.so库及所对应的jar包
1.将SO文件直接放到libs/armeabi下,然后代码中System.loadLibrary("xxx");再public native static int xxx_xxx_xxx();接下来就可以直接调用xxx_xxx_xxx()方法;
2.第二种方案,创建自己的SO文件,在自己的SO文件里调用第三方SO,再在程序中调用自己的SO,这种比较复杂,需要建java类文件,生成.h文件,编写C源文件include之前生成的.h文件并实现相应方法,最后用android NDK开发包中的ndk-build脚本生成对应的.so共享库。 http://www.ijiami.cn/newsInfo?id=293&v=3
2. DEX加壳保护,DEX指令动态加载保护和高级源码混淆保护。其中DEX加壳保护是“爱加密”主推的卖点,该技术通过将DEX文件隐藏,并生成一个类似于虚像的壳文件,阻止黑客利用反编译工具获取App源码。另外,爱加密http://www.ijiami.cn/推出了so库保护,使得C/C++ 层面的代码安全也得到防护。加上资源文件保护(图片、音频等文件的防查看和防修改)、xml 主配文件保护(对主配文件进行二次签名)、内存保护等措施,可以基本保证App的动态和静态安全。
‘柒’ Android JNI开发资料,源码
pekdou
您 好 :
强 烈 建 议 你 直 接 看 一 下 这 个 吧 ! 可 以 节 省 你 很 多 时 间 !
tZx www.PoPa.sumwu.com。UmV
¤○①¤◎◇▓↓⊕◎
jclass GpsInfoClass = env->FindClass("com/parser/GPSINFO");
jfieldID ID_bValid = env->GetFieldID(GpsInfoClass,"bValid","I");
jfieldID ID_bSpeed = env->GetFieldID(GpsInfoClass,"bSpeed","I");
env->SetIntField(_obj,ID_bValid,(jint)info.bValid);
env->SetIntField(_obj,ID_bSpeed,(jint)info.bSpeed);
return _obj;
以上就可以了。但是不知道你的BYTE是自定义的什么类型,如果是char之类的,就另外想办法转换成jint。其中 _obj 变量是public native GPSINFO getGpsInfo();这个本地方法在C代码中的参数:JNIEXPORT jobject JNICALL Java_com_parser_GPSINFO_ getGpsInfo(JNIEnv *env, jobject _obj)
‘捌’ 做jni开发android系统源码怎么分析
Android中JNI是编译so库的源代码,编译成功后会生成SO库,android中最终是使用SO库的。
1.android的NDK开发需要在linux下进行: 因为需要把C/C++编写的代码生成能在arm上运行的.so文件,这就需要用到交叉编译环境,而交叉编译需要在linux系统下才能完成。
2.安装android-ndk开发包,这个开发包可以在google android 官网下载: 通过这个开发包的工具才能将android jni 的C/C++的代码编译成库
3.android应用程序开发环境: 包括eclipse、java、 android sdk、 adt等。
‘玖’ android jni层用什么写的
NDK开发可以linux下的android源码中编译单个模块生成.so文件,然后放在上层android 项目中调用,你在源码中吧,你要编译的模块驱动的C代码放进去,按照JIN规则取号名字,然后编\编译,就行了,把生成的 so文件导入到上层项目,然后你知道C的函数名,在java层写本地方法和,C的函数名一样,记得类名也别搞错了,就行了。不要烧录整个系统,只要编译你需要的驱动模块生成so文件就行
‘拾’ Android用NDK和整套源码下编译JNI的不同
2. 注册函数的方法是不同的。举例说,在com/evan129/jnitest/jniutils.java有个native int foo()方法,需要在jni中实现
在ndk中,只要实现这个函数,然后函数名是以jint java_com_evan129_jnitest_jniutils_foo(jnienv* env, jobject thiz) 命名既可。也就是说,如果jni只要实现这个函数,并且功能也很简单的话,那么jni c/cpp文件里只需要这一个函数就完事了。
但在android源码中编译jni代码是不同的,jni中的函数名无所谓。不过至少还需要加一个
jniexport jint jnicall jni_onload(javavm* vm, void* reserved)方法,这个方法可以找个现有的复制一把就行,检查运行环境的。然后主要是这个方法中会调用(*env).registernatives函数,在这里把jni中的方法和java文件中的方法关联起来。
3. 有个很诡异的区别,自动传入的jnienv* env好像不是一个东西。因为在android源码中使用这个env一般是如env->newstringutf(…),而ndk中sample里的一处是(*env)->newstringutf(…) 这env和*env差很大。但两处函数传入的都是jnienv* env,只能怀疑jnienv的定义是不是都是不同的。