android开发——关于编写JNI

最近由于要开发android支付应用,实现刷卡读取磁卡的数据功能,需要编写JNI调用C语言底层库,在学习过程中也遇到了一些困难和问题,在这里记录下来,希望能给遇到同样问题的朋友提供帮助,避免走弯路。通过一个简单的调用c语言输出“hello”语句的例子来介绍如何编写JNI。
工程如下:


TestActivity.java:调用JNI方法,输出hello语句。
JniTest.java: 编写native方法,调用C语言方法,让TestActivity.java调用。
jni:在创建工程的时候自行创建,放编译好的so动态链接库。

1.在android工程中写native方法。
文件JniTest.java
  1. package com.android.jni;  
  2.   
  3. public class JniTest {  
  4.   
  5.      public static native String hello ();  
  6. }  

2. 编译h头文件(windows环境下)
打开控制台,进入工程目录(F:\androidDemo\test)
cd F:\android\test

输入如下命令编译h头文件
javah -classpath bin /classes -d jni com.android.jni.JniTest


-classpath ——类路径 bin/classes
-d ——保存目录:jni
com.android.jni.JniTest:包名+类名

这时候jni文件夹下就多出了一个h头文件——com_android_jni_JniTest.h。

3.编写C文件。
新建一个C文件——JniTest.c,实现com_android_jni_JniTest.h里的方法。
文件JniTest.c:
  1. #include "com_android_jni_JniTest.h"  
  2. #include <stdio.h>  
  3.   
  4. /* 
  5.  * Class:     com_android_jni_JniTest 
  6.  * Method:    hello 
  7.  * Signature: ()Ljava/lang/String; 
  8.  */  
  9. JNIEXPORT jstring JNICALL Java_com_android_jni_JniTest_hello  
  10.   (JNIEnv * env, jclass cla){  
  11.     return (*env)->NewStringUTF(env, "hello");  
  12.   }  

注:在h头文件中没有写上参数名,如env和cla,在c文件需要补上。

4.编写Android.mk文件。
在jni目录下新建Android.mk文件,内容如下:
[plain] view plain copy
  1. LOCAL_PATH := $(call my-dir)  
  2.   
  3. include $(CLEAR_VARS)  
  4.   
  5. LOCAL_MODULE    := JniTest  
  6. LOCAL_SRC_FILES := JniTest.c  
  7.   
  8. include $(BUILD_SHARED_LIBRARY)  

该文件中的一些变量对应的含义如下:
LOCAL_SRC_FILES -编译的源文件
LOCAL_MODULE -编译的目标对象

4.编译so动态链接库
由于编译so动态链接库需要Linux环境,如果你的操作系统是windows,可以安装cygwin模拟Linux环境,然后安装NDK即可,如果你是Linux环境,那么恭喜你,可以省略一步,直接安装NDK即可,若你是ubuntu环境,那么可以直接参考我之前的文章,(Ubuntu环境下配置NDK)其他环境就需要你自己google下了,过程应该大同小异了。
进入test工程(由于NDK配置路径问题,我将工程拷到ndk目录下的samples里)(F:\android\android-ndk-r7b\samples\test)

输入编译so命令
$NDK/ndk-build

若出现如上显示,则代表编译成功。

5.加载so文件
在JniTest.java中 添加加载so文件代码,具体代码如下:
  1. package com.android.jni;  
  2.   
  3. public class JniTest {  
  4.   
  5.      static {   
  6.            System. loadLibrary("JniTest"); //加载so动态链接库  
  7.            }   
  8.      public static native String hello();  
  9. }  

在JniTest.java调用hello方法,具体代码如下:
  1. package com.android.test;  
  2.   
  3. import com.android.jni.JniTest;  
  4.   
  5. import android.app.Activity;  
  6. import android.os.Bundle;  
  7. import android.widget.TextView;  
  8.   
  9. public class TestActivity extends Activity {  
  10.      private TextView tv;  
  11.     /** Called when the activity is first created. */  
  12.     @Override  
  13.     public void onCreate(Bundle savedInstanceState) {  
  14.         super.onCreate(savedInstanceState);  
  15.         setContentView(R.layout. main);  
  16.         tv=(TextView)findViewById(R.id. tv);  
  17.         tv.setText(JniTest.hello());  
  18.     }  
  19. }  

main.xml:
  1. <?xml version="1.0" encoding"utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width"fill_parent"  
  4.     android:layout_height"fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <TextView  
  8.         android:id"@+id/tv"  
  9.         android:layout_width"fill_parent"  
  10.         android:layout_height"wrap_content"  
  11.         android:text"@string/hello" />  
  12.   
  13. </LinearLayout>  

运行结果如下:


大功告成,若有其他不明白的地方,随时和我联系,我一定尽力帮助,大家互相学习!若有不对的地方,也请各位前辈们指正,谢谢!

在编写JNI的过程中,也遇到了一些问题,编译不成功,问题和解决办法如下:
问题1.
Android NDK:Your APP_BUILD_SCRIPT points to an unknow files: ./jni/Android.mk
若出现该问题,是由于没有编写Android.mk文件。

问题2.
arm-linux-androideabi-gcc.exe:CreateProcess: no such file or directory
可能是内存溢出问题,只要关闭eclipse或者占内存很大的软件即可。

问题3.
error:parameter name omitted

方法缺少参数名。由于h头文件是没有参数名的,所以很容易在C文件忘记加上,例如:
  1. JNIEXPORT jstring JNICALL Java_com_android_jni_JniTest_hello  
  2.   (JNIEnv *, jclass){  
  3.      return (*env)->NewStringUTF(env, "hello");  
  4.   }  
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值