用Android NDK实现四则运算

Android NDK开发环境搭建,请见:http://patmusing.blog.163.com/blog/static/135834960201111311022896/

 

Step1:     创建一个Android项目


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图1

 


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图2

点击Finish,项目就创建好了。

 

Step2:     创建一个Java类,规定Native动态库的名称,以及其中需要实现的方法。

如下图选中NDK02/src/com.pnf.ndk/New/Class,


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图3

 

指定类名为NativeLibrary,


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图4

 

编辑NativeLibrary.java,


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图5

 

NativeLibrary.java的内容如下:

package com.pnf.ndk;

 

public class NativeLibrary

{

         // 装载动态库ndk02

         static

         {

                   System.loadLibrary("ndk02");

         }

        

         // 将两个整数相加,返回它们的和

         public native int add( int x, int y );

        

         // 将两个整数相减,返回它们的差

         public native int min( int x, int y );

        

         // 将两个整数相乘,返回它们的积

         public native int mul(int x, int y);

 

         // 将两个整数相除,返回它们的商

         public native int divide(int x, int y);

}

System.loadLibrary("ndk02");中的动态库ndk02,可以是Windows平台上的ndk02.dll,也可以是Unix/Linux平台上的ndk02.so,在JNI中,loadLibrary的参数只是动态库的,不包括后缀的文件名。

 

Step3:     创建C头文件

启动Cygwin,进入到项目的bin子目录,用javah –jni com.pnf.ndk.NativeLibrary命令,将在bin目录下,会根据NativeLibrary.java生成一个C语言头文件 - com_pnf_ndk_NativeLibrary.h


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图06

 

在Cygwin模拟的Unix环境中,Windows系统中的所有目录,都被映射在/cygdrive目录之下,比如Windows中的E盘根目录,在Cygwin中,就是/cygdrive/e。我们的项目在Eclipse的Workspace(目录E:\Patrick\Workspace\Android)中,项目名称是NDK02,因此该项目的下的bin子目录,就是E:\Patrick\Workspace\Android\NDK02\bin。

 

在文件浏览器中,我们可以如下图看到新生成的com_pnf_ndk_NativeLibrary.h:


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图07

 

这个头文件的名字,实际上就是Nativelibrary类的全名决定的。NativeLibrary类的全名是com.pnf.ndk.NativeLibrary,而生成的C语言头文件的名称为com_pnf_ndk_NativeLibrary.h。

 

com_pnf_ndk_NativeLibrary.h文件的内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class com_pnf_ndk_NativeLibrary */

 

#ifndef _Included_com_pnf_ndk_NativeLibrary

#define _Included_com_pnf_ndk_NativeLibrary

#ifdef __cplusplus

extern "C" {

#endif

/*

 * Class:     com_pnf_ndk_NativeLibrary

 * Method:    add

 * Signature: (II)I

 */

JNIEXPORT jint JNICALL Java_com_pnf_ndk_NativeLibrary_add

  (JNIEnv *, jobject, jint, jint);

 

/*

 * Class:     com_pnf_ndk_NativeLibrary

 * Method:    min

 * Signature: (II)I

 */

JNIEXPORT jint JNICALL Java_com_pnf_ndk_NativeLibrary_min

  (JNIEnv *, jobject, jint, jint);

 

/*

 * Class:     com_pnf_ndk_NativeLibrary

 * Method:    mul

 * Signature: (II)I

 */

JNIEXPORT jint JNICALL Java_com_pnf_ndk_NativeLibrary_mul

  (JNIEnv *, jobject, jint, jint);

 

/*

 * Class:     com_pnf_ndk_NativeLibrary

 * Method:    divide

 * Signature: (II)I

 */

JNIEXPORT jint JNICALL Java_com_pnf_ndk_NativeLibrary_divide

  (JNIEnv *, jobject, jint, jint);

 

#ifdef __cplusplus

}

#endif

#endif

正如第一行注释说的那样,不要直接编辑这个自动生成的文件。

 

在Eclispe环境中,NDK02项目根节点下,创建一个文件夹jni,


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图08

 


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图09

 

jni文件夹所在的位置如下图所示:


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图10

 

现在将生成的头文件com_pnf_ndk_NativeLibrary.h,从E:\Patrick\Workspace\Android\NDK02\bin目录,直接拖到Eclipse中的jni文件夹下面。


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图11

 

完成后,jni文件夹下面就有com_pnf_ndk_NativeLibrary.h了,


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图12

 

Step4:     编写C代码

在jni文件夹里面创建一个文件ndk02.c,


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图13

 


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图14

 

我们将在ndk02.c里面,实现com_pnf_ndk_NativeLibrary.h头文件中声明的4个方法,其具体内容如下:

#include "com_pnf_ndk_NativeLibrary.h"

 

JNIEXPORT jint JNICALL Java_com_pnf_ndk_NativeLibrary_add

  (JNIEnv * env, jobject obj, jint value1, jint value2)

{

         return (value1 + value2);

}

 

JNIEXPORT jint JNICALL Java_com_pnf_ndk_NativeLibrary_min

  (JNIEnv * env, jobject obj, jint value1, jint value2)

{

         return (value1 - value2);

}

 

JNIEXPORT jint JNICALL Java_com_pnf_ndk_NativeLibrary_mul

  (JNIEnv * env, jobject obj, jint value1, jint value2)

{

         return (value1 * value2);

}

 

JNIEXPORT jint JNICALL Java_com_pnf_ndk_NativeLibrary_divide

  (JNIEnv * env, jobject obj, jint value1, jint value2)

{

         return (value1 / value2);

}

 

Step5:     编写make文件 - Android.mk

在jni文件夹里面创建一个文件Android.mk,


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图15

 


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图16

 

编辑Android.mk,是其内容如下:

LOCAL_PATH := $(call my-dir)

 

include $(CLEAR_VARS)

 

# Here we give our module name and source file(s)

LOCAL_MODULE          := ndk02

LOCAL_SRC_FILES       := ndk02.c

 

include $(BUILD_SHARED_LIBRARY)

 

注意:

1.        LOCAL_MODULE := ndk02中的“ndk02”,指定了将要生成动态库(ndk02.so)的名称,它必须要和NativeLibrary类中的System.loadLibrary("ndk02");里面的“ndk02”保持一致。

2.        LOCAL_SRC_FILES := ndk02.c中的“ndk02.c”必须和Step4中的C源文件的文件名保持一致。


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图17

 

Step6:     Build动态库

在Cygwin控制台中,进入NDK02项目所在的目录,然后调用ndk-build命令。操作过程如下:


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图18

 

注意:ndk安装在D:\android-ndk-r5b,其中有个工具ndk-build,就是专门用来根据Android.mk指定的内容,build动态库的。

 

如上图所示,生成了一个动态库libndk02.so。在Unix/Linux环境下库文件前面都会有“lib”,它表示这个文件是一个库文件,在代码中使用它时,必须忽略这三个字母,就像在NativeLibrary类中所写的那样。

 

在Eclipse中,选中项目根节点NDK02,再按F5键刷新NDK02项目,


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图19

 

如上图,我们将看到在出现了一个新文件夹libs,其下有一个文件 – libndk02.so。

 

Step7:     在NDK02Activity中,调用libndk02.so中的Native代码

首先准备NDK02Activity的界面。


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图20

 

完善NDK02/res/layout下面的main.xml,使其内容如下:

<?xml version="1.0" encoding="utf-8"?>

<AbsoluteLayout android:layout_width="fill_parent"

         android:layout_height="fill_parent"

         xmlns:android="http://schemas.android.com/apk/res/android"

         <EditText android:id="@+id/ed_operand1"

                   android:layout_width="83px"

                   android:layout_height="wrap_content"

                   android:text=""

                   android:textSize="18sp"

                   android:layout_x="6px"

                   android:layout_y="12px"

         >

         </EditText>

         <Button android:id="@+id/btn_operator"

                   android:layout_width="36px"

                   android:layout_height="36px"

                   android:text="+"

                   android:layout_x="90px"

                   android:layout_y="16px"

         >

         </Button>

         <EditText android:id="@+id/ed_operand2"

                   android:layout_width="83px"

                   android:layout_height="wrap_content"

                   android:text=""

                   android:textSize="18sp"

                   android:layout_x="127px"

                   android:layout_y="12px"

         >

         </EditText>

         <Button android:id="@+id/btn_calculate"

                   android:layout_width="50px"

                   android:layout_height="wrap_content"

                   android:text="="

                   android:layout_x="215px"

                   android:layout_y="12px"

         >

         </Button>

         <TextView android:id="@+id/tv_result"

                   android:layout_width="wrap_content"

                   android:layout_height="wrap_content"

                   android:text="0"

                   android:layout_x="7px"

                   android:layout_y="67px"

         >

         </TextView>

</AbsoluteLayout>

 

再完善NDK02Activity.java,使其内容如下:

package com.pnf.ndk;

 

import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextView;

 

public class NDK02Activity extends Activity

implements

OnClickListener

{

         // 声明界面元素

         private EditText ed_operand1;

         private Button btn_operator;

         private EditText ed_operand2;

         private Button btn_calculate;

         private TextView tv_result;

        

         // 声明一个NativeLibrary对象

         private NativeLibrary nb;

        

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState)

    {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

       

        // 获取界面元素对象

        ed_operand1 = (EditText)this.findViewById(R.id.ed_operand1);

        btn_operator = (Button)this.findViewById(R.id.btn_operator);

        ed_operand2 = (EditText)this.findViewById(R.id.ed_operand2);

        btn_calculate = (Button)this.findViewById(R.id.btn_calculate);

        tv_result = (TextView)this.findViewById(R.id.tv_result);

       

        // 设定字体大小

        ed_operand1.setTextSize(16.0f);

        ed_operand2.setTextSize(16.0f);

        tv_result.setTextSize(60.0f);

       

        // 给按钮增加OnClickListener

        btn_operator.setOnClickListener(this);

        btn_calculate.setOnClickListener(this);

       

        // 初始化NativeLibrary对象nb

        nb = new NativeLibrary();

    }

 

         public void onClick(View v)

         {

                   switch(v.getId())

                   {

                   // 点击按钮btn_operator时:

                   case R.id.btn_operator:

                            // 如果btn_operator当前的Text是"+",那么就让其Text变成"-"

                            if(btn_operator.getText().toString().equals("+"))

                            {

                                     btn_operator.setText("-");

                                     return;

                            }

                            // 如果btn_operator当前的Text是"-",那么就让其Text变成"*"

                            if(btn_operator.getText().toString().equals("-"))

                            {

                                     btn_operator.setText("*");

                                     return;

                            }

                            // 如果btn_operator当前的Text是"*",那么就让其Text变成"/"

                            if(btn_operator.getText().toString().equals("*"))

                            {

                                     btn_operator.setText("/");

                                     return;

                            }

                            // 如果btn_operator当前的Text是"/",那么就让其Text变成"+"

                            if(btn_operator.getText().toString().equals("/"))

                            {

                                     btn_operator.setText("+");

                                     return;

                            }

                            break;

                   // 如果点击按钮btn_calculate:

                   case R.id.btn_calculate:

                            // 首先从两个EditText中,获取操作数。

                            int operand1 = Integer.parseInt(ed_operand1.getText().toString());

                            int operand2 = Integer.parseInt(ed_operand2.getText().toString());

                           

                            // result准备用于存放结果

                            String result = "";

                           

                            // 如果btn_operator按钮上的Text是"+"

                            if(btn_operator.getText().toString().equals("+"))

                            {

                                     // 调用nb对象中规定的Native方法add,并将结果转型为String

                                     result = String.valueOf(nb.add(operand1, operand2));

                            }

                           

                            // 如果btn_operator按钮上的Text是"-"

                            if(btn_operator.getText().toString().equals("-"))

                            {

                                     // 调用nb对象中规定的Native方法min,并将结果转型为String

                                     result = String.valueOf(nb.min(operand1, operand2));

                            }

                           

                            // 如果btn_operator按钮上的Text是"*"

                            if(btn_operator.getText().toString().equals("*"))

                            {

                                     // 调用nb对象中规定的Native方法mul,并将结果转型为String

                                     result = String.valueOf(nb.mul(operand1, operand2));

                            }

                           

                            // 如果btn_operator按钮上的Text是"/"

                            if(btn_operator.getText().toString().equals("/"))

                            {

                                     // 调用nb对象中规定的Native方法divide,并将结果转型为String

                                     result = String.valueOf(nb.divide(operand1, operand2));

                            }

                            // 将计算结果显示到tv_result中。

                            tv_result.setText(result);

                            break;

                   default:

                            break;

                   }

         }

}

 

Step8:     运行


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图21

 

运行结果。

加法运算:


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图22

 

减法运算:


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图23

 

乘法运算:


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图24

 

除法运算:


用Android NDK实现四则运算 - 玄机逸士 - 玄机逸士博客

图25

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值