当前位置:首页 » 操作系统 » androidjni源码

androidjni源码

发布时间: 2022-06-11 14:34:53

‘壹’ 如何在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的定义是不是都是不同的。

热点内容
跳转页源码 发布:2024-09-17 03:13:05 浏览:542
html文件上传表单 发布:2024-09-17 03:08:02 浏览:783
聊天软件编程 发布:2024-09-17 03:00:07 浏览:725
linuxoracle安装路径 发布:2024-09-17 01:57:29 浏览:688
两个安卓手机照片怎么同步 发布:2024-09-17 01:51:53 浏览:207
cf编译后没有黑框跳出来 发布:2024-09-17 01:46:54 浏览:249
安卓怎么禁用应用读取列表 发布:2024-09-17 01:46:45 浏览:524
win10设密码在哪里 发布:2024-09-17 01:33:32 浏览:662
情逢敌手迅雷下载ftp 发布:2024-09-17 01:32:35 浏览:337
安卓如何让软件按照步骤自动运行 发布:2024-09-17 01:28:27 浏览:197