2009-10-09 43 views
3

我想将我的Android项目中的小型,精益和平均基于C的解析器合并到一起。过去我已经完成了JNI编程,但没有任何类型的Android本机(C)开发。我的计划是将C库编译成SO,并在它的周围创建JNI包装,我将在我的应用程序中使用它。这是可以/应该完成的吗?第二个也是最重要的问题 - 我如何将.so包含到我的APK中?它会去哪里?Android - JNI准则

回答

2

使用的Android NDK
下载无文档Android NDK 1.6

这将节省您写的lib JNI层,也将安装该应用程序在您的应用程序数据文件夹的lib文件夹。

+0

你能在“不写JNI层”有何评论?我需要使用从我的Java代码的C LIB方法你说,NDK会自动创建一个包装给我吗? – Bostone 2009-10-09 15:14:40

+0

是的,会的。你所要做的就是使用“native”关键字来存放库中的函数。它也有一些非常简单的样本。 – bhatt4982 2009-10-09 17:19:29

5

根据多少数据传递和多久我严重怀疑一个Java/JNI/C将执行比原来的Java实现更快。

传递了一个“Java的诠释”以外的任何一个“C长”调用JNI数据转换例程这是什么,但精简和意思。

所以,除非你的JNI程序符合模式:数据

  • 通量小。
  • 做很多很多的工作,在C.
  • 通小结果集返回。

你会比原生的Java实现慢得多。如果你坚持使用“native”数据类型(int,char,String)的基本“C”类似java操作(+, - ,*,==,>),并避免花哨的库,Java的性能将几乎与C.

的Java性能剩下的bug的熊火起来的JVM,让一切准备所花费的时间,但因为你是从Java程序出发这是一个非问题。

的另一个原因“慢” Java性能是人们坚持不必要的工厂,集装箱,XML等豆类等,其中普通,简单的方法,会做的工作做得更好。

3

在你的Android应用程序的根文件夹中创建一个JNI文件夹(其中有SRC,RES).Place码(1)将其命名为someshared-lib.c。

(1)

Java_YourPackageName_YourClassNameWhereYoudeclareYourNativeFunction_NativeFuntionName(JNIEnv* env,jobject thiz) 
{ 


//your c code , the JNI will act as a wrapper for it 

return (*env)->NewStringUTF(env, "<string to pass or you can mention jchar * type string >"); 

} 

(2)在Java文件

package YourPackageName; 

public class YourClassNameWhereYoudeclareYourNativeFunction extends Activity 
{ 

    public native String NativeFuntionName(); 
    String returnValue = NativeFuntionName(); 


} 

(3)在Android.mk做到这一点:

LOCAL_PATH:= $(叫我-DIR )

包括$(CLEAR_VARS)

LOCAL_MODULE:= someshared-lib //注意libname与c文件名相同

LOCAL_SRC_FILES:= someshared-lib。ç//这是你放置代码的文件(1)

包括$(BUILD_SHARED_LIBRARY)

出口的NDK,建立 (做外销PATH =:$ PATH

转到JNI文件夹的上面创建为: 执行NDK-build命令

你会得到一个库中形成的在应用程序根folder.While建筑lib文件夹中形成someshared-lib的和运行应用程序lication这将让捆绑用的APK,并会得到安装在device.To验证这一点,你可以去

/数据/数据/ your_package_name/lib文件夹。

该应用程序在/ data/data/your_package_name/lib(也是/ system/lib以及)文件夹中搜索此lib并将其用于从Android应用程序生成的动态调用(JNI)。

现在,如果你想返回字符串以外什么,你必须改变以下用C文件上面的方法declration:

Java_YourPackageName_YourClassNameWhereYoudeclareYourNativeFunction_NativeFuntionName(JNIEnv* env,jclass obj,jobject thiz) 
{ 
jfieldID fid; 
jboolean enable_flag; 

//Pass the class object having all the variable from the android app to the JNI in the jclass obj and access its members using the field ID and using Get and Set firld ID. 

clazz = (*env)->GetObjectClass(env, info); 
fid = (*env)->GetFieldID(env,clazz,"some_variable","X"); //"X" - type of variable for boolean it //is Z , for INtezer it is I, for double it is D, 

在参考本document详细的解释

//for getting teh value fomr the JNI 
enable_flag = (*env)->GetBooleanField(env, **thiz**, fid); 


//for setting the value 

fid = (*env)->GetFieldID(env,clazz,"other_float_variable","D"); 
(*env)->SetDoubleField(env,**thiz**,fid,other_float_variable); 



} 

而且Android应用程序必须传递结构的Class对象。 e.g

(2)现在将变为:

包YourPackageName;

public class YourClassNameWhereYoudeclareYourNativeFunction extends Activity 
{ 

    public native String NativeFuntionName(); 
    String returnValue = NativeFuntionName(exampleStruct exst); 

其中exampleStruct:

公共类exampleStruct {

protected boolean some_variable = 0;//no log saving by default 
protected float other_float_variable = 0; 

}

} 

希望这有助于。