android JNI的.so库调用

在一篇博客中看到一篇文章,感觉描述的还可以:


在前面的博客中介绍的都是使用java开发Android应用,这篇博客将介绍java通过使用jni调用c语言做开发

为了更加形象的介绍jni,先观察下面的图片,下图表示的是整个android系统架构



图中从上到下的结构依次是:
Application:表示应用层,其实就是指android手机上的应用

Application Framework:表示应用框架层,我们平时用java开发app就是使用应用框架层提供的API做开发

Libraries:android类库,使用C/C++开发的android类库

Android Runtime:android运行环境

Linux Kernel:Linux内核


通过上图可知Android系统分为五个部分,分别是Application(应用层)、Application Framework(应用框架)、Librarise(Android 类库)、Android Runtime(Android 运行环境)、Linux Kernel(Linux内核),且android应用框架使用java开发的,android类库使用c/c++开发的,为了使得java开发应用框架能调用c/c++开发的android类库,android中引入了一个jni,通过jni可以实现java调用c/c++,c/c++调用java



开发jni需要准备的工具:
参考:android NDK的下载-文件太大

Android ndk,Android NDK的下载地址是:   android NDK的下载-文件太大


下载完成后将ndk解压的一个任意的目录下,我解压在 D:\develop

建议文件目录不要带空格,解压后将ndk所在的路径添加到环境变量中



打开android ndk后,可以看到android ndk的目录结构如下:


android ndk目录结构介绍:

docs:帮助文档

build/tools:linux的批处理文件

platforms:编译c代码需要使用的头文件和类库

prebuilt:预编译使用的二进制可执行文件

sample:jni的使用例子

source:ndk的源码

toolchains:工具链

ndk-build.cmd:编译打包c代码的一个指令


使用ndk实现一个简单的Hello World程序

第一步:使用eclipse创建一个Android工程,并且将工程的名称命名为HelloJni

第二步:修改activity_main.xml文件,在布局上添加一个按钮点击按钮后调用c语言写的代码 


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:paddingBottom="@dimen/activity_vertical_margin"  
    android:paddingLeft="@dimen/activity_horizontal_margin"  
    android:paddingRight="@dimen/activity_horizontal_margin"  
    android:paddingTop="@dimen/activity_vertical_margin"  
    tools:context=".MainActivity" >  
      
    <Button   
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="调用c语言代码"  
        android:onClick="click"/>  
  
</RelativeLayout>  



第三步: 在创建好的android工程下新建一个jni文件夹


第四步:在jni文件夹下新建一个hello.c文件,并在hello.c文件中添加下面的代码 


#include <stdio.h>  
#include <stdlib.h>  
#include <jni.h>  
  
/*** 
 * 第一个参数:java虚拟机的内存地址 
 * 第二个参数:调用helloFromC方法的java对象 
 */  
Java_com_example_hellojni_MainActivity_helloFromC(JNIEnv* env, jobject obj) {  
  
    //创建一个c语言的字符串,并且初始化字符串  
    char* arr = "hello world jni !";  
  
    //把c语言的字符串转换成java的字符串  
    jstring jstr = (*env)->NewStringUTF(env, arr);  
  
    //返回字符串  
    return jstr;  
}  




第五步:在jni文件夹下新建一个Android.mk文件,并在Android.mk中添加下面的代码 


LOCAL_PATH := $(call my-dir)  
  
   include $(CLEAR_VARS)  
     
#编译生成的文件的类库叫什么名字  
   LOCAL_MODULE    := hello  
     
   #要编译的c文件  
   LOCAL_SRC_FILES := Hello.c  
  
   include $(BUILD_SHARED_LIBRARY)  





第六步: 编译android ndk程序

1、打开命令行,并且进入到jni所在的目录



2、输入ndk-build.cml命令编译android ndk



3、看到下图所示的提示表示android ndk编译成功



4、此时打开libs文件夹下的armeabi文件夹,可以看到armeabi文件夹下生成了一个libhello.so文件

      这个就是Android ndk编译后生成的文件,在后面就可以直接使用libhello.so文件



最后一步:使用通过ndk编译好的,修改MainActivity.java文件


package com.example.hellojni;  
  
import android.app.Activity;  
import android.os.Bundle;  
import android.view.View;  
import android.widget.Toast;  
  
public class MainActivity extends Activity {  
      
    static {  
          
        //加载打包完毕的so类库  
        System.loadLibrary("hello");  
    }  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
    }  
      
    //调用c语言代码按钮响应函数  
    public void click(View view) {  
          
        //使用吐司对话框显示c语言代码中的函数helloFromC()的返回值  
        Toast.makeText(this, helloFromC(), Toast.LENGTH_SHORT).show();  
    }  
      
    //定义一个本地方法,方法体由C语言实现  
    public native String helloFromC();  
}  




-------------------------------------运行之后的效果------------------------------------------------
运行android程序后手机上会显示下图所示的界面

点击按钮后弹出吐司,并且在吐司中显示"hello world jni !"表示Android成功的调用了c语言开发的jni程序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个过程涉及到JNI(Java Native Interface)调用,它是一个Java虚拟机的桥接API,用于在Java和本地代码之间提供交互。JNI调用.so过程是指在Java程序中调用本地动态链接(.so文件)的过程,它可以提高程序的性能,并且可以让Java程序访问本地系统的资源。 ### 回答2: JNI调用.so文件的过程如下: JNI(Java Native Interface)是Java编程语言的一种编程框架,它允许Java代码调用C、C++或其他本地语言编写的代码。而.so(共享目标文件)是一种在Linux系统中广泛使用的动态链接文件。通过JNI调用.so文件,可以在Java代码中调用本地代码完成一些特定的功能。 首先,在Java代码中使用关键字native标识一个方法,表明该方法是一个本地方法。然后,通过Java编译器编译Java源文件,生成.class字节码文件。 接下来,在通过Java虚拟机(JVM)运行的过程中,当调用到native方法时,JVM会去查找包含该本地方法的动态链接文件.so。 JVM通过JNI提供的函数,在文件中找到对应的本地方法。这些函数包括:JavaVM结构体、JNI环境函数等。 在找到本地方法之后,JVM将Java的参数转换为本地方法可接受的参数类型,并将这些参数传递给本地方法。 本地方法执行完毕后,通过JNI将结果返回给Java。 总结来说,JNI调用.so文件的过程主要包括以下几个步骤:标识本地方法、编译Java源文件生成.class文件、JVM加载.so文件、通过JNI将参数传递给本地方法、本地方法执行完毕后将结果返回给Java。 通过JNI调用.so文件,可以在Java代码中灵活地调用本地代码,实现一些底层功能,提高程序的效率和灵活性。 ### 回答3: JNI(Java Native Interface)是一种允许Java程序与本地代码进行交互的技术。在JNI中,.so文件是指Linux系统下的共享文件,也称为共享对象文件。 JNI调用.so文件的过程如下: 1. 编写Native方法:在Java代码中,先声明需要调用的本地方法,使用`native`关键字修饰,例如:`public native void nativeMethod();`。 2. 生成包含JNI方法的头文件:在命令行中使用`javac`命令编译Java代码生成.class文件,然后使用`javah`命令生成包含JNI方法的头文件。例如:`javah MyClass`,将生成一个名为`MyClass.h`的头文件。 3. 实现Native方法:根据生成的头文件,编写本地代码实现Native方法,可以使用C或C++来编写。将实现的代码保存为.c或.cpp文件,例如:`MyClass.c`或`MyClass.cpp`。 4. 编写JNI配置文件:创建一个名为`Android.mk`的文件,定义需要编译的源文件、依赖、编译配置等信息。在该文件中,使用`include`命令引入NDK的配置文件。 5. 编译本地代码:在命令行中使用NDK提供的编译命令对本地代码进行编译,生成.so文件。例如:`ndk-build`。 6. 将.so文件与Java代码关联:在Java代码中加载.so文件,使用`System.loadLibrary("文件名")`方法。例如:`System.loadLibrary("mylibrary")`。该方法会在运行时将.so文件加载到JVM中。 7. 调用Native方法:在Java代码中,通过调用定义的Native方法来执行本地代码。例如:`nativeMethod();`。 8. 运行程序:在命令行或IDE中运行Java程序,即可进行JNI调用.so文件的过程。 总结:通过编写Native方法、生成头文件、实现本地代码、编写JNI配置文件、编译本地代码、关联.so文件和调用Native方法这些步骤,就可以完成JNI调用.so文件的过程。JNI技术可以方便地在Java程序与本地代码之间进行交互,提供了一种扩展Java功能的方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值