当前位置:首页 » 安卓系统 » androidjni调用过程

androidjni调用过程

发布时间: 2022-04-12 10:16:08

① 如何在Android下使用JNI

关于如何在Android使用JNI调用C/C++代码库,网上已经有很多优秀的文章了,这里说一个大概过程吧:

首先需要懂C,其次要明白JNI的开发流程,然后还要知道NDK如何使用

1、在java代码中声明了一个native本地方法

Public native String helloFromc();

2、在项目目录中创建JNI文件夹

3、在JNI文件夹里面创建C文件,按照规范写代码

Jstring
Java_com_cheng_jnitest_MainActivity_helloFromc(JNIEnv* env,jobject obj)

4、用ndk-build指令编译
编译前需要配置Android.mk文件
//指定编译的文件夹,指定当前的目录
LOCAL_PATH := $(call my-dir)

//编译器在编译的时候会产生很多临时变量,中间变量最好在编译前清空所有的临时变量

include $(CLEAR_VARS)

//编译完成后的模块名
LOCAL_MOUDLE := hello
//编译的源文件

LOCAL_SRC_FILES:=hello.c

//编译一个动态库

//动态库.so 只包含运行的函数,不包含依赖,所以体积小,运行的时候回去系统寻找依赖

//静态库.a 包含所有的函数和运行的依赖,所以体积大,包含所有的api

include $(BUILD_SHARED_LIBRARY)

5、生成了一个so动态库,放到了libs里面

6、项目中引入依赖库

Static{

System.loadLibrary("hello");

}

② android studio怎么调用jni

(1)老版本,方法如下: task NativeLibs(type: Copy) { from(new File(project(':MyProject').buildDir, 'native-libs')) { include '**/*.so' } into new File(buildDir, 'native-libs') } tasks.withType(Compile) { compileTask -> compileTask.dependsOn NativeLibs } clean.dependsOn 'cleanCopyNativeLibs' tasks.withType(com.android.build.gradle.PackageApplicationTask) { pkgTask -> pkgTask.jniDir new File(buildDir, 'native-libs') } (2)新版本三种方法: (2.1)打包前先生成.Jar文件后自动解包到apk文件 task nativeLibsToJar(type: Zip, description: 'create a jar archive of the native libs') { destinationDir file("$buildDir/native-libs") baseName 'native-libs' extension 'jar' from fileTree(dir: 'libs', include: '**/*.so') into 'lib/' } tasks.withType(Compile) { compileTask -> compileTask.dependsOn(nativeLibsToJar) } 下面一句话就是打包生成目录(build\native-libs)中的.jar文件 compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar') (2.2)手动生成.Jar文件后自动解包到apk文件 这个方式需要自己手动进行.SO文件压缩,具体步骤为:将所有需要使用的.so文件压缩为.zip文件(zip中的文件目录结构为: lib/armeabi/*.so)然后把zip文件后缀改为.Jar然后放到libs生成apk就ok 默认就是自动打包所有.Jar文件: dependencies { compile fileTree(dir: 'libs', include: '*.jar') } (2.3)这也就是现在正在使用的方式(推荐) ,其实无非就是把.SO文件打包到APK的lib文件夹中,假如仔细阅读了Gradle的使用方法,自然就知道其实Gradle官方在新版已经自动实现了打包.SO文件的.很简单级就是在配置的android节点下加入下面的内容就ok: sourceSets { main { jniLibs.srcDirs = ['libs'] } } 其他地方无需修改,整个项目的配置文件如下: apply plugin: 'android' android { compileSdkVersion 19 buildToolsVersion "19.0.0" defaultConfig { minSdkVersion 16 targetSdkVersion 19 versionCode 1 versionName "1.0" } buildTypes { release { runProguard false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' } } sourceSets { main { jniLibs.srcDirs = ['libs'] } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) }

③ android studio ndk怎么调用

android studio ndk调用过程如下:

通过jniaes案例说明调用NDK层配置过程

而我们通过底层来判断签名是否正确,如果正确则继续执行核心代码,否则退出程序,这样就可以防止别人恶意反编译,并进行二次打包。

首先去官网下载一个最新的NDK,随便放到哪都行,像我放在D:DevAndroidandroid-ndk-r10d.

(1) 新建一个项目:名称JniAes

首先在java类中添加native接口,注意写好native接口和System.loadLibrary()即可。代码如下:

1 public synchronized static native String getFromNativeIv();
2 public synchronized static native String getStringFromNative();
3 public synchronized static native int jniCheckAPP(Context context);
4

然后build project得到其中中间文件,我们关注的是.class文件。编译OK以后生成的class文件在AS工程的如下目录:

aesapp

(2)接下来跟class文件生成相应的.h头文件,执行如下命令即可

点击"View->Tool Windows->Terminal" 即在Studio中进行终端命令行工具.执行如下命令生成c语言头文件.
javah -d jni -classpath c:
android-16android.jar;....uildintermediatesclassesdebug com.aes.jniaes.MainActivity

(3)然后将刚才的 .h文件剪切过来。在jni目录下新建一个c文件,随意取名,我的叫strk.c 。

strk.c文件,用于实现核心代码逻辑,判断包名.哈希值是否合法,如果返回1,为合法。反之,则不合法。入口方法为:
jint Java_com_aes_jniaes_MainActivity_jniCheckAPP(JNIEnv* env, jobject context,
jobject thiz)

接下来在工程的local.properties文件中添加NDK路径(上面下载好的那个NDK),类似其中的SDK路径一样,我的添加后如下:

sdk.dir=D:\Dev\Android\android-sdk-windows
ndk.dir=D:\Dev\Android\android-ndk-r10d

(4)接下来在app mole目录下的build.gradle中设置库文件名(生成的so文件名)。找到gradle文件的defaultConfig这项,在里面添加如下内容:

defaultConfig {
applicationId "com.aes.jniaes"
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"

ndk {
moleName "checkapp-jni" //生成的so名字
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库。目前可有可无。
}
}

(5)最后就是添加静态初始化loadLibrary代码,添加如下:

static {
System.loadLibrary("checkapp-jni"); //so文件的名字
}

编译出来的so文件在aesappuildintermediates dkdebuglib目录下

那么如何将编译好的so文件进行使用,可以通过如下方式:

二 .引用so文件

(1).在“src/main”目录中新建名为“jniLibs”的目录;

(2).将so文件复制、粘贴到“jniLibs”目录内。

④ 如何在android下使用jni

第一步:

使用Java编写HelloWorld 的Android应用程序:

复制代码
package com.lucyfyr;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class HelloWorld extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.v("fresne", printJNI("I am HelloWorld Activity"));
}
static
{
//加载库文件
System.loadLibrary("HelloWorldJni");
}
//声明原生函数 参数为String类型 返回类型为String
private native String printJNI(String inputStr);
}
复制代码


这一步可以使用eclipse来生成一个App;

因为eclipse会自动为咱们编译此Java文件,后面要是用到。

第二步:

生成共享库的头文件:

进入到eclipse生成的Android Project中 :/HelloWorld/bin/classes/com/lucyfyr/ 下:

可以看到里面后很多后缀为.class的文件,就是eclipse为咱们自动编译好了的java文件,其中就有:

HelloWorld.class文件。

退回到classes一级目录:/HelloWorld/bin/classes/

执行如下命令:

javah com.lucyfyr.HelloWorld

生成文件:com_lucyfyr_HelloWorld.h复制代码
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_lucyfyr_HelloWorld */
#ifndef _Included_com_lucyfyr_HelloWorld
#define _Included_com_lucyfyr_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_lucyfyr_HelloWorld
* Method: printJNI
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_lucyfyr_HelloWorld_printJNI
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
复制代码


可以看到自动生成对应的函数:Java_com_lucyfyr_HelloWorld_printJNI

Java_ + 包名(com.lucyfyr) + 类名(HelloWorld) + 接口名(printJNI):必须要按此JNI规范来操作;

java虚拟机就可以在com.simon.HelloWorld类调用printJNI接口的时候自动找到这个C实现的Native函数调用。

当然函数名太长,可以在.c文件中通过函数名映射表来实现简化。

第三步:

实现JNI原生函数源文件:

新建com_lucyfyr_HelloWorld.c文件:复制代码
#include <jni.h>
#define LOG_TAG "HelloWorld"
#include <utils/Log.h>
/* Native interface, it will be call in java code */
JNIEXPORT jstring JNICALL Java_com_lucyfyr_HelloWorld_printJNI(JNIEnv *env, jobject obj,jstring inputStr)
{
LOGI("fresne Hello World From libhelloworld.so!");
// 从 instring 字符串取得指向字符串 UTF 编码的指针
const char *str =
(const char *)(*env)->GetStringUTFChars( env,inputStr, JNI_FALSE );
LOGI("fresne--->%s",(const char *)str);
// 通知虚拟机本地代码不再需要通过 str 访问 Java 字符串。
(*env)->ReleaseStringUTFChars(env, inputStr, (const char *)str );
return (*env)->NewStringUTF(env, "Hello World! I am Native interface");
}

/* This function will be call when the library first be load.
* You can do some init in the libray. return which version jni it support.
*/
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
void *venv;
LOGI("fresne----->JNI_OnLoad!");
if ((*vm)->GetEnv(vm, (void**)&venv, JNI_VERSION_1_4) != JNI_OK) {
LOGE("fresne--->ERROR: GetEnv failed");
return -1;
}
return JNI_VERSION_1_4;
}
复制代码


OnLoadJava_com_lucyfyr_HelloWorld_printJNI

函数里面做一些log输出 注意JNI中的log输出的不同。

JNI_OnLoad函数JNI规范定义的,当共享库第一次被加载的时候会被回调,

这个函数里面可以进行一些初始化工作,比如注册函数映射表,缓存一些变量等,

最后返回当前环境所支持的JNI环境。这里只是简单的返回当前JNI环境。第四步:

编译生成so库

编译com_lucyfyr_HelloWorld.c成so库可以和app一起编译,也可以都单独编译。

在当前目录下建立jni文件夹:HelloWorld/jni/

下建立Android.mk ,并将com_lucyfyr_HelloWorld.c和 com_lucyfyr_HelloWorld.h 拷贝到进去

编写编译生成so库的Android.mk文件:复制代码
LOCAL_PATH:= $(call my-dir)
# 一个完整模块编译
include $(CLEAR_VARS)
LOCAL_SRC_FILES:=com_lucyfyr_HelloWorld.c
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_MODULE := libHelloWorldJni
LOCAL_SHARED_LIBRARIES := libutils
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_TAGS :=optional
include $(BUILD_SHARED_LIBRARY)
复制代码


系统变量解析:

LOCAL_PATH - 编译时的目录
$(call 目录,目录….) 目录引入操作符
如该目录下有个文件夹名称 src,则可以这样写 $(call src),那么就会得到 src 目录的完整路径

include $(CLEAR_VARS) -清除之前的一些系统变量
LOCAL_MODULE - 编译生成的目标对象
LOCAL_SRC_FILES - 编译的源文件
LOCAL_C_INCLUDES - 需要包含的头文件目录
LOCAL_SHARED_LIBRARIES - 链接时需要的外部库
LOCAL_PRELINK_MODULE - 是否需要prelink处理
include$(BUILD_SHARED_LIBRARY) - 指明要编译成动态库

⑤  android中,请简述jni的调用过程

1)安装和下载Cygwin,下载 Android NDK
2)在ndk项目中JNI接口的设计
3)使用C/C++实现本地方法
4)JNI生成动态链接库.so文件
5)将动态链接库复制到java工程,在java工程中调用,运行java工程即可

⑥ android中如何调用jni需要ndk吗

ndk是一个可以在android开发工具上面开发C或者c++的插件,所以是需要的,调用jni需要在java代码里面声明一个native方法,然后在c或者c++里面实现那个方法,编译成.so库文件,在需要使用的地方调用。

⑦ 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调用静态库

androidstudiondk调用过程如下:通过jniaes案例说明调用NDK层配置过程而我们通过底层来判断签名是否正确,如果正确则继续执行核心代码,否则退出程序,这样就可以防止别人恶意反编译,并进行二次打包。首先去官网下载一个最新的NDK,随便放到哪都行,像我放在D:\Dev\Android\android-ndk-r10d.(1)新建一个项目:名称JniAes首先在java类中添加native接口,注意写好native接口和System.loadLibrary()即可。代码如下:();();(Contextcontext);4然后buildproject得到其中中间文件,我们关注的是.class文件。编译OK以后生成的class文件在AS工程的如下目录:aes\app\build\intermediates\classes\debug\android\(2)接下来跟class文件生成相应的.h头文件,执行如下命令即可点击"View->ToolWindows->Terminal"即在Studio中进行终端命令行工具.执行如下命令生成c语言头文件.javah-djni-classpathc:\Users\sodinochen\AppData\Local\Android\sdk\platforms\android-16\android.jar;..\..\build\intermediates\classes\debugcom.aes.jniaes.MainActivity(3)然后将刚才的.h文件剪切过来。在jni目录下新建一个c文件,随意取名,我的叫strk.c。strk.c文件,用于实现核心代码逻辑,判断包名.哈希值是否合法,如果返回1,为合法。反之,则不合法。入口方法为:jintJava_com_aes_jniaes_MainActivity_jniCheckAPP(JNIEnv*env,jobjectcontext, jobjectthiz)接下来在工程的local.properties文件中添加NDK路径(上面下载好的那个NDK),类似其中的SDK路径一样,我的添加后如下:sdk.dir=D\:\\Dev\\Android\\android-sdk-windowsndk.dir=D\:\\Dev\\Android\\android-ndk-r10d(4)接下来在appmole目录下的build.gradle中设置库文件名(生成的so文件名)。找到gradle文件的defaultConfig这项,在里面添加如下内容:defaultConfig{ applicationId"com.aes.jniaes" minSdkVersion15 targetSdkVersion22 versionCode1 versionName"1.0" ndk{ moleName"checkapp-jni" //生成的so名字 abiFilters"armeabi","armeabi-v7a","x86" //输出指定三种abi体系结构下的so库。目前可有可无。 } }(5)最后就是添加静态初始化loadLibrary代码,添加如下:static{ System.loadLibrary("checkapp-jni"); //so文件的名字 }编译出来的so文件在aes\app\build\intermediates\ndk\debug\lib目录下 那么如何将编译好的so文件进行使用,可以通过如下方式:二. 引用so文件(1).在“src/main”目录中新建名为“jniLibs”的目录;(2).将so文件复制、粘贴到“jniLibs”目录内。

⑨ android怎么用APK调用JNI简单实例

制作Android的内置APK,调用C或者C++去调用底层接口:
环境配置:
eclipse要配置NDK插件和系统环境,我用的是WIN7,先去下载NDK,解压后就是一个目录,把路径记住,去XP电脑配置下环境,就像配置Java环境一样,把路径写到系统环境的PATH就好了(这样就可以编译JNI了)。然后在配置eclipse的NDK插件,点击eclipse的WINDOW/PREFERNCES,弹出框了后点击android/NDK,有个路径选择,一样选择你下载好解压的目录(选择后提示不是有效的NDK目录的时候,你在NDK目录里面新建一个文件,名字写:ndk-build,没有后缀)
http://blog.csdn.net/csh86277516/article/details/52639023

⑩ 如何调用 androidruntime中注册的jni

千锋扣丁学堂Android开发学习为您解答: Android系统运用Java语言,而Java语言的数据基本中没有无符号类型,Android系统下底层发送的信息一般是“\n\r”的机制。开始做项目时候,两条路一条是运用ADB做项目,另一条是运用JNI和ADB做项目,前期使用运用ADB做项目,运用两个类Runtime and Process.其中把操作串口的执行C文件通过ADB工具放入Android系统的system目录下。在运用Android上层应用框架层控制并运行项目。从中出现问题,那就是项目失败率比较高,而项目是直接面对客服的,无法让客服对这一切满足。后面就开发了另外一条运用JNI和ADB,解决上述问题,保证成功升级。 JNI能解决Java没有C program无符号类型的问题,通过把JNI与Java的调用解决问题,Java无法直接操作和控制Linux内核层的串口,而C语言可以,在Android 系统层存在lib库,里面包含C语言库,打包成动态链接库so文件,Android系统上层可以直接调用动态链接库so文件。 Android系统下底层发送的信息一般是“\n\r”,而Android系统外接设备不接受 “\n\r”数据,这样也会导致项目的失败。经过实验对Android 系统的串口参数进行设置,把Android系统下底层发送的信息附带“\n\r”给过滤,如此一来就解决问题。

热点内容
内置存储卡可以拆吗 发布:2025-05-18 04:16:35 浏览:335
编译原理课时设置 发布:2025-05-18 04:13:28 浏览:378
linux中进入ip地址服务器 发布:2025-05-18 04:11:21 浏览:612
java用什么软件写 发布:2025-05-18 03:56:19 浏览:32
linux配置vim编译c 发布:2025-05-18 03:55:07 浏览:107
砸百鬼脚本 发布:2025-05-18 03:53:34 浏览:943
安卓手机如何拍视频和苹果一样 发布:2025-05-18 03:40:47 浏览:739
为什么安卓手机连不上苹果7热点 发布:2025-05-18 03:40:13 浏览:803
网卡访问 发布:2025-05-18 03:35:04 浏览:510
接收和发送服务器地址 发布:2025-05-18 03:33:48 浏览:371