• Android(java)学习笔记201:JNI之helloword案例(利用NDK工具)


    1. 逻辑思路过程图:

    2.下面通过一个HelloWorld案例来说明一下JNI利用NDK开发过程(步骤)

    分析:我们在Win7系统下编译的C语言代码,我们知道C语言依赖操作系统,不能跨平台,所以我们要通过NDK工具把在Win7系统下编写的C代码,转化为可以在Linux(Linux2.6.6---Android内核)运行的二进制代码,最后通过JNI协议规范,Android中java代码就可以调用这个转化后的二进制代码运行。

    (1)在Eclipse中新建一个Android工程,命名为"HelloWorld",如下:

    接下来来到Android工程布局文件activity_main.xml,如下:

     1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     xmlns:tools="http://schemas.android.com/tools"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent"
     5     android:paddingBottom="@dimen/activity_vertical_margin"
     6     android:paddingLeft="@dimen/activity_horizontal_margin"
     7     android:paddingRight="@dimen/activity_horizontal_margin"
     8     android:paddingTop="@dimen/activity_vertical_margin"
     9     tools:context="com.himi.helloworld.MainActivity" >
    10 
    11     <Button
    12         android:layout_centerHorizontal="true"
    13         android:layout_centerVertical="true"
    14         android:layout_width="wrap_content"
    15         android:layout_height="wrap_content"
    16         android:text="问C要Hello"
    17         android:onClick="getHello"/>
    18 
    19 </RelativeLayout>

    布局效果如下:

    (2)来到Android工程的MainActivity.java,如下:

    在Java中声明native方法

     1 package com.himi.helloworld;
     2 
     3 import android.app.Activity;
     4 import android.os.Bundle;
     5 import android.view.View;
     6 import android.widget.Toast;
     7 
     8 public class MainActivity extends Activity {
     9 
    10     //通过JNI,调用C/C++代码,在C中实现的 (不是在Java层实现的)
    11     public native String getHelloFromC();
    12     @Override
    13     protected void onCreate(Bundle savedInstanceState) {
    14         super.onCreate(savedInstanceState);
    15         setContentView(R.layout.activity_main);
    16     }
    17 
    18     
    19     /**
    20      * 按钮点击事件,获取C的hello问候
    21      * @param view
    22      */
    23     public void getHello(View view) {
    24         Toast.makeText(this, "C代码问候:"+getHelloFromC(), 0).show();
    25     }
    26     
    27 }

    就这样一个Android工程的就搭建好了,接下来关于C代码

    (3)接下来在"HelloWorld"工程目录下,新建一个文件夹命名为" jni ",如下:

    (4)在刚刚新建的" jni "文件夹下,我们新建一个hello.c文件,同时我们拷贝 jni.h 文件到 jni文件下,如下:

    • hello.c  :

     1 #include <jni.h>
     2 
     3 char* getHello()
     4 {
     5     ////////
     6     return "hello Android From C";
     7 }
     8 
     9 
    10 //jni协议给java调用
    11 //  返回类型   方法名(Java_包名(使用"_"把包名分割)_类名_方法名  (参数)
    12 
    13 //JNIEnv* env   jni的结构体数据,jni系统实现 ;   obj java对象  调用该jni方法的对象
    14 jstring Java_com_himi_helloworld_MainActivity_getHelloFromC(JNIEnv* env, jobject obj)
    15 {
    16     char* res = getHello();//获取到C代码字符串结果
    17     /**
    18      * (**env).GetVersion(env);
    19      * (*env)->GetVerison(env);
    20      */
    21     //jstring (*NewStringUTF)(JNIEnv*, const chat*);
    22     jstring jres = (**env).NewStringUTF(env,res);
    23 
    24     return jres;
    25 }

    代码中,上面的getHello()是C语言代码;

    下面的定义的 Java_com_himi_helloworld_MainActivity_getHelloFromC()方法是JNI协议的规范,这样写java才能调用getHello()方法,Java_com_himi_helloworld_MainActivity_getHelloFromC()起到过渡作用。

    Java_com_himi_helloworld_MainActivity_getHelloFromC()方法的密码法则如下:

                             Java_com_himi_helloworld_MainActivity_getHelloFromC()

                             Java_(包名,包名使用'_'分割)_类名_Android(java)调用的方法名()

     备注:jni.h文件作用是数据类型翻译,将JAVA语言的数据类型利用C的语法重新定义,实现2种不同的语法之间的数据类型转换。

    • jni.h(导入进来的,NDK中platform有):

    文件内容太多,截图一部分让大家感受一下

    (5)上面准备好的hello.c 和jni.h都是在Win7系统下编写的,但是我们想让它在Android(Linux2.6.6)环境下运行,不得不介绍一个工具:NDK

    搜索下载NDK,我的是win7 32位系统,下载的是android-ndk-r9c_x86.zip,大家看到了这是一个压缩文件,只要解压即可(无需安装),解压效果如下:

    接下来要在环境变量中配置PATH路径,这样才能直接在Win7 系统的命令行下运行,我的配置完毕了,下面进入命令行窗口使用 "ndk-build",如下:

    出现这样的问题,一方面说明ndk工具配置正确,另一方面说明没有正确运行。这个问题是因为:这需要在工程目录下运行命令行才能,什么工程呢?就是我们编写的Android工程”HelloWorld",让我们先找到”HelloWorld"的工程目录,如下:

    然后,在上面的工程目录下,运行" ndk-build"的cmd命令,如下:

    虽然,出现了警告,但是说明之前的错误解决了。现在出现这个问题是因为红色部分:我们的Android工程下jni文件夹下找不到Android.mk文件,该怎么办呢?我们自己在jni文件下创建这个Android.mk文件即可,如下:

    新建完了Android.mk,但是内部的内容该写什么呢?不急,大家来到ndk的解压目录中docs(帮助文档)文件夹下,如下:

    打开之后的效果图如下:

    复制到Android工程的Android.mk文件下,如下:

    修改之后,文件如下:

    这时候我们再来运行"ndk-build"命令如下:

    刷新工程,看到如下结果,Window下动态库文件(.dll) Linux下动态库文件(.so):

    上面我们是在win7系统下,生成了可以在Linux系统下运行的代码libhellojni.so,这就是前面提到的交叉编译,这里使用的交叉编译的工具是NDK.

    (6)接下来就是让java代码调用" libhellojni.so",进入MainActivity,如下:

    (7)布署这个Android的"HelloWorld"工程到模拟器下,效果如下:

    点击"问C要Hello",如下:

  • 相关阅读:
    Java实现各种内部排序算法
    Java实现堆排序(大根堆)
    Java对象的序列化和反序列化
    Java实现链式存储的二叉查找树(递归方法)
    337. House Robber III(包含I和II)
    318. Maximum Product of Word Lengths
    114. Flatten Binary Tree to Linked List
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    96. Unique Binary Search Trees(I 和 II)
  • 原文地址:https://www.cnblogs.com/hebao0514/p/4811565.html
Copyright © 2020-2023  润新知