【问题标题】:Android - JNI guidelinesAndroid - JNI 指南
【发布时间】:2009-10-09 05:03:06
【问题描述】:

我想将基于 C 的小型、精简和平均的解析器合并到我的 Android 项目中。我过去做过 JNI 编程,但没有在 Android 上进行任何类型的原生 (C) 开发。我的计划是将 C lib 编译成 SO 并围绕它创建 JNI 包装器,我将在我的应用程序中使用它。这是可以/应该怎么做的吗?第二个也是最重要的问题 - 如何将 .so 包含到我的 APK 中?它会去哪里?

【问题讨论】:

    标签: android java-native-interface


    【解决方案1】:

    取决于您传递的数据量以及我严重怀疑 Java/JNI/C 的执行速度是否会比本机 Java 实现更快的频率。

    将“Java Int”以外的任何内容传递给“C long”会调用 JNI 数据转换例程,这些例程绝不是精简和卑鄙的。

    所以除非你的 JNI 例程符合这个模式:

    • 传递少量数据。
    • 在 C 中做大量的工作。
    • 传回小结果集。

    您将比本地 java 实现慢得多。如果您坚持使用“本机”数据类型(int、char、String)的 Java 操作(+、-、*、==、>)之类的基本“C”,并避免使用花哨的库,Java 的执行速度几乎与C.

    Java 性能的剩余缺陷是启动 JVM 并让一切正常运行所花费的时间,但是当您从 Java 程序开始时,这不是问题。

    Java 性能“慢”的另一个原因是人们坚持使用不必要的工厂、容器、xml bean 等。在这些地方,简单明了的方法会做得更好。

    【讨论】:

      【解决方案2】:

      在您的 Android 根应用程序文件夹中创建一个 JNI 文件夹(其中有 src、res)。将代码 (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 := $(call my-dir)

      包括 $(CLEAR_VARS)

      LOCAL_MODULE := someshared-lib //注意libname和c文件名一样

      LOCAL_SRC_FILES := someshared-lib.c //这是您放置代码的文件 (1)

      包括 $(BUILD_SHARED_LIBRARY)

      导出您的 ndk-build (导出 PATH=:$PATH

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

      您将在应用程序根文件夹中形成的 lib 文件夹中获得一个形成的库 someshared-lib。在构建和运行应用程序时,这将与apk 并将安装在设备中。要验证这一点,您可以转到

      /data/data/your_package_name/lib 文件夹。

      应用程序在 /data/data/your_package_name/lib(也包括 /system/lib)文件夹中搜索了此库,并将其用于 Android 应用程序进行的动态调用 (JNI)。

      现在如果你想返回字符串以外的任何内容,你必须在 c 文件中更改上述方法声明,如下所示:

      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 对象。 例如

      (2) 现在将变为:

      打包YourPackageName;

      public class YourClassNameWhereYoudeclareYourNativeFunction extends Activity
      {
      
          public native String  NativeFuntionName();
          String returnValue = NativeFuntionName( exampleStruct exst);
      

      示例结构:

      公共类exampleStruct {

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

      }

      }
      

      希望这会有所帮助。

      【讨论】:

        【解决方案3】:

        使用 Android NDK
        下载n个文档Android NDK 1.6

        这将使您免于为 lib 编写 JNI 层,并将应用程序安装在您的应用程序数据文件夹的 lib 文件夹中。

        【讨论】:

        • 你能评论一下“不写JNI层”吗?我需要使用我的 Java 代码中的 C lib 方法,你是说 NDK 会自动为我创建一个包装器吗?
        • 是的,它会的。您所要做的就是对库中的函数使用“native”关键字。它也有一些非常简单的示例。
        【解决方案4】:

        【讨论】:

        • 现在有点过时了。现在很多都简单了。他将 JNI 与在 Android 上无用的 C# 进行了比较。
        猜你喜欢
        • 1970-01-01
        • 2023-03-25
        • 2011-09-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多