2024年1月22日发(作者:)

我们看一下如何在Android环境下引用/system/lib下的.so文件(若您也对此有所了解,还望不吝赐教后面的问题,先谢!)。

为避免讲得混淆,先将我的代码的结构贴出来。

首先,新建Android工程:AndroidJniTest,在中的代码如下:

[java]view plaincopyprint?

1. package ;

2. import ty;

3. import ;

4. publicclass AndroidJniTestActivity extends Activity {

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

6. @Override

7. publicvoid onCreate(Bundle savedInstanceState) {

8. te(savedInstanceState);

9. setContentView();

10. brary("test");

11. CallNative callnative = new CallNative();

12. byte[] cmd = {(byte)'u004c'};

13. int a = md(cmd, "/system/lib");

14.

15. }

16. }

package ;import ty; import ;public class AndroidJniTestActivity extends Activity

{ /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState)

{ te(savedInstanceState); setContentView(); brary("test"); CallNative callnative =

new CallNative(); byte[] cmd = {(byte)'u004c'}; int a = md(cmd, "/system/lib"); }}

再在包下建立文件: 代码:

[java]view plaincopyprint?

1. package ;

2. publicclass CallNative {

3. publicnativebyte[] readCmd(String path);

4. publicnativeint writeCmd(byte[] cmd, String path);

5. }

package ;public class CallNative { public native byte[] readCmd(String path); public native int writeCmd(byte[] cmd,

String path);}

利用javah工具创建本地库文件的头文件mars_com_CallNative.h 代码:

[cpp]view plaincopyprint?

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

2. #include

3. /* Header for class mars_com_CallNative */

4. #ifndef _Included_mars_com_CallNative

5. #define _Included_mars_com_CallNative

6. #ifdef __cplusplus

7. extern"C" {

8. #endif

9. /*

10. * Class: mars_com_CallNative

11. * Method: readCmd

12. * Signature: (Ljava/lang/String;)[B

13. */

14. JNIEXPORT jbyteArray JNICALL Java_mars_com_CallNative_readCmd

15. (JNIEnv *, jobject, jstring);

16. /*

17. * Class: mars_com_CallNative

18. * Method: writeCmd

19. * Signature: ([BLjava/lang/String;)I

20. */

21. JNIEXPORT jint JNICALL Java_mars_com_CallNative_writeCmd

22. (JNIEnv *, jobject, jbyteArray, jstring);

23. #ifdef __cplusplus

24. }

25. #endif

26. #endif

/* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class mars_com_CallNative */ #ifndef

_Included_mars_com_CallNative#define _Included_mars_com_CallNative #ifdef __cplusplusextern "C" {#endif/* * Class:

mars_com_CallNative * Method: readCmd * Signature: (Ljava/lang/String;)[B */ JNIEXPORT jbyteArray JNICALL

Java_mars_com_CallNative_readCmd (JNIEnv *, jobject, jstring);/* * Class: mars_com_CallNative * Method: writeCmd *

Signature: ([BLjava/lang/String;)I */ JNIEXPORT jint JNICALL Java_mars_com_CallNative_writeCmd (JNIEnv *, jobject,

jbyteArray, jstring);#ifdef __cplusplus}#endif#endif

[cpp]view plaincopyprint?

1.

  

  

[java]view plaincopyprint?

1.

  

 

至于如何生成此头文件,可自行学习,这里不多讲了

第二,在工程目录下建立文件夹:jni,将文件mars_com_CallNative.h 拷贝到此目录下,再在此目录下建立文件test.c,代码:

#include"mars_com_CallNative.h"

#include

#include

#include

#include

#include

#include

#include

#include

#include"include/telephony/ril.h"

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "keymatch", __VA_ARGS__)

JNIEXPORT jbyteArray JNICALL Java_mars_com_CallNative_readCmd(JNIEnv *evn, jobject obj, jstring jstr)

{

exit(0);

}

JNIEXPORT jint JNICALL Java_mars_com_CallNative_writeCmd(JNIEnv *evn, jobject jobj, jbyteArray jba, jstring jstr)

{

return 56;

}

jint JNI_OnLoad(JavaVM* vm, void* reserved) {

LOGD("JNI ONLOAD success!");

char *path = "/system/lib/";

void* filehandle0 = dlopen(path, RTLD_LAZY|RTLD_GLOBAL ); //引用path指向的库:/system/lib/

char *ll;

int pid;

if(filehandle0)

{

LOGD("open so success!");

char*(*requesttostring)(int);

if( 0 == pid)

{

sleep(1);//子进程睡眠一秒

requesttostring = (char *(*)(int))dlsym(filehandle0, "requestToString");

pid = fork();

if( requesttostring )

{

LOGD("call function requesttostring OK!");

ll = requesttostring(RIL_REQUEST_GET_NEIGHBORING_CELL_IDS);

//RIL_REQUEST_GET_NEIGHBORING_CELL_IDS定义在include/telephony/ril.h中

LOGD("the value of requesttostring is %s", *ll);

}

else

{

LOGD("call function getinformation! ERROR!");

}

LOGD("ok");

}

elseif(0 < pid)

{

LOGD("in the parent %sn",getpid());

}

else LOGD("fork error");

}

}

将Android源码hardware/ril下的include文件夹也拷贝到jni文件夹下(因为在requesttostring(RIL_REQUEST_GET_NEIGHBORING_CELL_IDS)中使用的RIL_REQUEST_GET_NEIGHBORING_CELL_IDS在include文件夹下的ril.h中定义了)。

在jni文件夹下新建文件,内容如下:

[plain]view plaincopyprint?

1. LOCAL_PATH := $(call my-dir)

2. include $(CLEAR_VARS)

3. LOCAL_MODULE := test

4. LOCAL_SRC_FILES := test.c

5. LOCAL_LDLIBS := -llog

6. LOCAL_CERTIFICATE := platform

7. include $(BUILD_SHARED_LIBRARY)

LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS)LOCAL_MODULE := testLOCAL_SRC_FILES := test.c

LOCAL_LDLIBS := -llogLOCAL_CERTIFICATE := platform include $(BUILD_SHARED_LIBRARY)

第三,接下来就是编译的时候了。在cygwin下 $ndk/ndk-build

显示编译通过了,F5刷新工程,发现在工程目录下多了一下文件夹:libs,其中就包含了生成的文件:

最后,运行。发现在Logcat下有这些信息:

。。。。。。

好了,问题来了。问题一、从绿色部分的内容来看,应该是成功引用了/system/lib/的,但为什么在上面只输出了

在test.c中,我用了fork创建了两个进程,而且在子进程中sleep(1),睡眠了一秒,按理说在这时应该运行父进程,也就是说应该运行如下部分代码

else if(0 < pid)

{

LOGD("in the parent %sn",getpid());

}

Logcat : in the parent + pid ,但问题是在运行时没有输出,这是why??

问题二、在Logcat中可以看到,程序跑着跑着就死了

是怎么死的呢?会不会是因为在模拟器中无法进行通信(是通信模块的一部分)?但如果是意外终止的话,模拟器中却一直是运行正常的,没有弹出意外终止的对话框。

这个问题困扰了我很久,希望能得到高人指点,谢谢!