jni调试
12年的時候寫過JNI但是又忘記得差不多了,現(xiàn)在重新寫了一次,發(fā)現(xiàn)碰到了幾個問題,寫下來記錄一下
第一步
應用程序java代碼
package com.example.helloworld;import java.util.Calendar;import android.os.Bundle; import android.app.Activity; import android.app.AlarmManager; import android.util.Log;public class AlarmTest extends Activity {AlarmManager aManager;Calendar currentTime = Calendar.getInstance();public static final int POWER_OFF_WAKE_UP = 8;//用來設置關機啟動的參數(shù) 平臺這邊已經設置好了@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Log.e("weiqifa", test());}public native String test();static {try{Log.i("JNI", "Trying to load libhelloworld.so");System.loadLibrary("helloWorld");}catch(UnsatisfiedLinkError ule){Log.e("JNI", "Warning : could not load the libhelloworld.so");}} }編譯一下,可以是eclipse編譯,也可以是java命令編譯
編譯后有下面的代碼結構和目錄
weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$ ls
AndroidManifest.xml? classes? classes.dex? dexedLibs? helloWorld.apk? res? resources.ap_
weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$
第二步
生成共享頭文件 這一步是最關鍵的關系到成功和失敗
weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$ javah -d header -classpath classes -jni com.example.helloworld.AlarmTest
weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$
這個命令比較關鍵 javah -d header 指的是在當前目錄下面生成這個頭文件,-classpath是指定classes的目錄就是第一步里面生成的
-jni指的是生成jni頭文件 com.example.helloworld這個是包名 AlarmTest是類名 這些都不能有錯
生成后如下
weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$ ls
AndroidManifest.xml? classes? classes.dex? dexedLibs? header? helloWorld.apk? res? resources.ap_
weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$ ls header/
com_example_helloworld_AlarmTest.h
weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$
剛開始不知道,運行經常出錯如下:
weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$ javah -jni com.example.helloworld
error: cannot access com.example.helloworld
class file for com.example.helloworld not found
javadoc: error - Class com.example.helloworld not found.
Error: No classes were specified on the command line.? Try -help.
weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/bin$
可以看到自動生成對應的函數(shù):Java_com_example_helloworld_AlarmTest_test
Java_ + 包名(com_example_helloworld) + 類名(AlarmTest) + 接口名(test):必須要按此JNI規(guī)范來操作;
第三步
通過.h來制作.c
看看我們的.c 我們只是需要.h里面那個函數(shù)名字,.h沒有被引用,也沒有參與編譯和預編譯
helloworld.c如下:
#include <string.h> #include <jni.h>JNIEXPORT jstring JNICALL Java_com_example_helloworld_AlarmTest_test(JNIEnv *env, jobject thiz) {return (*env)->NewStringUTF(env,"weiqifa hello for JNI"); }第四步
生成so文件
看一下我們的mk文件
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS)LOCAL_MODULE := helloWorld LOCAL_SRC_FILES := helloWorld.cinclude $(BUILD_SHARED_LIBRARY)會生成如下的so文件:
weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/libs/armeabi$ ls
libhelloWorld.so
weiqifa@weiqifa-Inspiron-3847:~/workspace/helloWorld/libs/armeabi$
第五步
執(zhí)行驗證
直接用eclipse安裝 或者用 adb push 進去 用adb的話要手動安裝so 文件并且改一下權限
10-20 03:06:45.241: E/weiqifa(12194): weiqifa hello for JNI
10-20 03:06:45.241: V/ActivityThread(12194): activityCreated r=ActivityRecord{41e7a890 token=android.os.BinderProxy@41e7a060 {com.example.helloworld/com.example.helloworld.AlarmTest}}
問題:
剛開始的時候,我在Android.mk里面寫的LOCAL_MODULE生成的模塊名稱是大寫W,helloWorld
但是在android源碼里面,我寫的
System.loadLibrary("helloWorld");里面的helloworld是小寫w,然后運行一直加載不成功,后面有個朋友幫我看了一下,找到原因,粗心大意啊。
總結
- 上一篇: 第4章 原子操作 第二节
- 下一篇: 日记html模板,【精选】初二日记模板集