Android 呼叫.so檔案 jni
阿新 • • 發佈:2019-01-28
android呼叫so
android虛擬機器不能直接呼叫底層裝置,我們如果要對底層裝置進行呼叫就需要用到so.
so使用C語言或C++編寫完成,使用ndk進行編譯,直接執行在linux核心中.
按jni呼叫so時基本型別可以直接互動,jstring使用時有點麻煩,所以我做一個jstring和char*進行轉換的例子.
第一步:
工程根目錄下建立jni目錄.libs目錄不用手動建立.
注意:這裡使用ndk_R7所以不需要用jdk去生成C檔案頭.
第二部:
java編寫介面檔案(Device.java)
- publicclass Device {
-
static
- System.loadLibrary("device");
- }
- publicnative String deviceTestString(String test);
- }
第三部:
編寫C檔案(devices.c)
這裡編寫的c程式碼屬於linux C範疇.
- #include <string.h>
- #include <jni.h>
-
char* jstringTostrM(JNIEnv* env, jstring jstr)
- {
- char* pStr = NULL;
- jclass jstrObj = (*env)->FindClass(env, "java/lang/String");
- jstring encode = (*env)->NewStringUTF(env, "utf-8");
- jmethodID methodId = (*env)->GetMethodID(env, jstrObj, "getBytes", "(Ljava/lang/String;)[B");
-
jbyteArray byteArray = (jbyteArray)(*env)->CallObjectMethod(env, jstr, methodId, encode);
- jsize strLen = (*env)->GetArrayLength(env, byteArray);
- jbyte *jBuf = (*env)->GetByteArrayElements(env, byteArray, JNI_FALSE);
- if (jBuf > 0)
- {
- pStr = (char*)malloc(strLen + 1);
- if (!pStr)
- {
- return NULL;
- }
- memcpy(pStr, jBuf, strLen);
- pStr[strLen] = 0;
- }
- (*env)->ReleaseByteArrayElements(env, byteArray, jBuf, 0);
- return pStr;
- }
- jstring Java_com_jack_Device_deviceTestString(JNIEnv* env,jclass clazz,jstring path){
- //system("echo devices.so test > /sdcard/log/log.txt");
- char * test = jstringTostrM(env,path);
- return (*env)->NewStringUTF(env, test);
- }
注意:C的函式命名規則:Java是jni標準必須有,com_jack_Device是Device.java檔案的全名,再下來才是C函式名
jstringTostrM函式必須寫在Java_com_jack_Device_deviceTestString函式前,如果不是必須要C檔案開頭進行宣告.
宣告程式碼:
- char* jstringTostrM(JNIEnv* env, jstring jstr);
android.mk檔案如下:
- LOCAL_PATH := $(call my-dir)
- include $(CLEAR_VARS)
- LOCAL_MODULE := device
- LOCAL_SRC_FILES := device.c
- include $(BUILD_SHARED_LIBRARY)
- include $(BUILD_EXECUTABLE)
編譯:
第五步:編寫java程式碼進行C函式呼叫:
- Device device = new Device();
- String test = device.deviceTestString("你好~!!!");
- Toast toast = Toast.makeText(Jack_ndk_jstringActivity.this, test, Toast.LENGTH_LONG);
- toast.setGravity(Gravity.TOP,0,150);
- toast.show();
- TextView text = (TextView) findViewById(R.id.text1);
- text.setText(test);
- <!-- 檔案許可權 -->
- <uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
- <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>