首页 > 代码库 > Jni开发编译中的几个错误

Jni开发编译中的几个错误

1、背景介绍

       最近有个项目,需要客户端发送短信,但是被360提示报毒了,还有一个问题就是不太安全,怎么办呢?这个时候,我们的处理方式是使用了JNI调用Java方法,来发送短信。但是在编译的过程中,出现了几个问题,这里来简单总结一下。


2、问题一

2.1 出错信息

这里直接贴出错误代码,以搜索引擎的强大,会很快就搜出来。

Android NDK: WARNING: APP_PLATFORM android-17 is larger than android:minSdkVersion 11 in ./AndroidManifest.xml    
[armeabi-v7a] Compile thumb  : sendmsg <= sendmsg.c
jni/sendmsg.c: In function 'Java_com_hello_jni_utils_JniUtils_sendSms':
jni/sendmsg.c:14:23: error: request for member 'FindClass' in something not a structure or union
jni/sendmsg.c:16:22: error: request for member 'GetStaticMethodID' in something not a structure or union
jni/sendmsg.c:18:20: error: request for member 'NewObject' in something not a structure or union
jni/sendmsg.c:21:8: error: request for member 'GetMethodID' in something not a structure or union
jni/sendmsg.c:25:7: error: request for member 'CallVoidMethod' in something not a structure or union
make.exe: *** [obj/local/armeabi-v7a/objs/sendmsg/sendmsg.o] Error 1

2.2 问题解析

        这个错误当中,主要的问题是,找不到这个方法。但是我明明在系统中定义了该方法呀,哪里出错了呢?

        我仔细检查了代码,发现代码并没有调用额外的方法,我在文件的头部也包含了相关头文件,如:

#include <jni.h>
#include <string.h>
#include <stdio.h>

        后来发现一个问题,我是将这个文件用C++编译过的,没有问题。移植的时候,将系统使用了C文件命名,就出错了,那我再改回去行不行?好吧,测试通过,可行。

2.3 原因解析

       深入分析之后,发现了是C语言语法格式与C++的差异导致的,如果是c程序,要用 (*env)->,如果是C++要用 env->。我在代码中,主要有这样的一个方法调用:

jobject sms = env->NewObject( smsclazz, get); 
jclass smsclazz = env->FindClass("android/telephony/SmsManager");
       在linux下如果.c文件中用 “env->” 编译会找不到此结构,必须用“(*env)->”,或者改成.cpp文件,以 c++的方式来编译。


3、问题二

3.1 问题描述

      在修改了2中的错误,再次编译的时候,发现一个问题,就是当我的文件修改成为了cpp文件之后,提示说c文件找不到,主要报错信息如下:

make.exe: *** No rule to make target `jni/sendmsg.c', needed by `obj/local/armeabi-v7a/objs/sendmsg/sendmsg.o'.  Stop.

       我挺纳闷的,我已经将c文件修改为cpp文件了呀,就算要提示,也应该提示cpp文件找不到才对呀。

3.2 解决方案猜测

       好吧,是不是我的配置文件不对呢,我去检查了一下,我已经将文件修改为了cpp命名文件,如下:

LOCAL_SRC_FILES := sendmsg.cpp
       我再仔细看看错误信息,说的是在make过程中,没有找到sendmsg.o文件。额,难道有缓存???将程序clean一下,出现一样的错误,暂时不去管他,看到目录下多出一个文件夹obj,如下:

3.3 解决方案

       删掉obj文件,重新clean一下,OK!


4、问题三

4.1 问题描述

      问题解决的差不多了,可是坑爹的又出现了一个问题,是什么呢?说是在链接的时候找不到这个方法,额,啥意思呀,我直接贴错误信息好了:

11-04 14:27:52.750: E/AndroidRuntime(27773): FATAL EXCEPTION: main
11-04 14:27:52.750: E/AndroidRuntime(27773): java.lang.UnsatisfiedLinkError: Native method not found: 

com.common.library.utils.JniUtils.sendSms:(Ljava/lang/String;Ljava/lang/String;)V
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at com.common.library.utils.JniUtils.sendSms(Native Method)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at com.paying.player.sms.SmsSendManager.sendSms(SmsSendManager.java:82)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at com.paying.player.sms.SmsSendManager.sendSms(SmsSendManager.java:115)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at com.paying.player.SplashActivity.sendSms(SplashActivity.java:98)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at com.paying.player.SplashActivity.onCreate(SplashActivity.java:47)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at android.app.Activity.performCreate(Activity.java:5184)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at com.qihoo360.mobilesafe.loader.b.callActivityOnCreate(SourceFile:81)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2078)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2139)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at android.app.ActivityThread.access$700(ActivityThread.java:143)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1241)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at android.os.Handler.dispatchMessage(Handler.java:99)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at android.os.Looper.loop(Looper.java:137)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at android.app.ActivityThread.main(ActivityThread.java:4963)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at java.lang.reflect.Method.invokeNative(Native Method)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at java.lang.reflect.Method.invoke(Method.java:511)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
11-04 14:27:52.750: E/AndroidRuntime(27773): 	at dalvik.system.NativeStart.main(Native Method)

4.2 解决方案

       其实出现这个问题挺坑爹的,首先,我看了下,是否已经使用了static静态代码块,将编译之后的so文件包含进来?代码如下:

static {
		System.loadLibrary("sendmsg");
	}
        已经包含了呀,没问题。

        那么,是不是参数列表不对呢?我仔细检查了一下,参数列表也没有问题。

        再看,是不是参数的返回值有问题,导致程序除了问题呢?仔细看看,也没有问题(java代码和c++代码都没问题)。

        坑爹了,到底什么地方出问题了,之前不是挺靠谱的么?我后来想起来,之前的时候用过一个头文件信息的,里面有一个继承c的语句,难道是这个问题?添加代码如下:

        ok,编译成功。

4.3 成功信息

       编译成功之后的信息,应该如下所示:



Jni开发编译中的几个错误