NDK构建和.so文件创建Android

7

我是新手,接触Android NDK不久。

我正在开发一个应用程序,需要Java代码以及C/C++代码。

因此,我需要使用Android NDK。

但是,我遇到了一个问题,我无法运行ndk-build,这会在Java和C/C++之间建立连接。

所以,请有经验的人帮我解决这个问题。

我在Windows和Linux上都尝试过,但是得到了相同的错误。

当我使用ndk-build时,我得到了这个错误。

/home/kamal/android-ndk-r8e/build/core/add-application.mk:128: Android NDK:      
Compile thumb : ndk <= native.c
jni/native.c: In function 'Java_com_example_demo_MainActivity_hello':  
jni/native.c:4:3: error: parameter name omitted
jni/native.c:4:3: error: parameter name omitted
jni/native.c:5:10: error: 'env' undeclared (first use in this function)
jni/native.c:5:10: note: each undeclared identifier is reported only once for each              function it appears in
jni/native.c: In function 'Java_com_example_demo_MainActivity_add':
jni/native.c:9:3: error: parameter name omitted
jni/native.c:9:3: error: parameter name omitted
jni/native.c:9:3: error: parameter name omitted
jni/native.c:9:3: error: parameter name omitted
jni/native.c:10:9: error: 'value1' undeclared (first use in this function) 
jni/native.c:10:18: error: 'value2' undeclared (first use in this function)
make: *** [obj/local/armeabi/objs/myjni/native.o] Error 1 
2个回答

21

首先,您会遇到这个错误是因为您没有声明参数,这是在Java和C/C++之间创建连接所必需的。

因此,我将发送我的代码以解决您的问题。

1.首先在Eclipse中创建Android项目。

  1. 在项目下创建文件夹->点击新建->然后选择文件夹并将其命名为jni。

  2. 在jni下再创建一个文件夹,命名为include。

  3. 创建Java类。

  4. Java类的名称为MainActivity.java,代码如下:

 package com.example.ndk;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

 public class MainActivity extends Activity {

 static {
     System.loadLibrary("myjni");
    }

/**
* Adds two integers, returning their sum
*/
public native int add( int v1, int v2 );

/**
* Returns Hello World string
*/
public native String hello();


@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

    }
  • 打开命令提示符或按下window+R键。

  • 进入目录-(workspace->项目名称->jni->include)。

  • 在该目录下运行命令。

  •     javah -classpath <project-name>/bin/classes;<ANDROID_SDK_HOME>\platforms\android-<xx>\android.jar -o HelloJNI.h com.example.test.MainActivity
    
  • 在此之后,我们可以在include文件夹下看到“HelloJNI.h”文件。

  • 检查“HelloJNI.h”中是否包含这些行

  • JNIEXPORT jint JNICALL Java_com_example_ndk_MainActivity_add(JNIEnv *, jobject, jint, jint);
    
    JNIEXPORT jstring JNICALL Java_com_example_ndk_MainActivity_hello (JNIEnv *, jobject);
    
  • 在jni目录下创建一个名为test.c的新文件(在该文件中使用第10点中提到的这两个点)

  •    #include <jni.h>
       #include "include/HelloJNI.h"
    
    JNIEXPORT jstring JNICALL Java_com_example_ndk_MainActivity_hello
        (JNIEnv *env, jobject javaThis) {
        return (*env)->NewStringUTF(env, "Hello");
    }
    
      JNIEXPORT jint JNICALL Java_com_example_ndk_MainActivity_add
          (JNIEnv *env, jobject javaThis, jint value1, jint value2){
    return (value1 + value2);
        }
    
  • 创建命名为Android.mk的jni新文件

  • LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE    := myjni       // from point 5 
     LOCAL_SRC_FILES := test.c     //from point 10 that we creare test.c
    
     include $(BUILD_SHARED_LIBRARY)
    
  • 创建新文件 NDKActivity.java

  •   package com.example.ndk;
    
      import android.app.Activity;
      import android.view.View.OnClickListener;
      import android.os.Bundle;
      import android.view.View;
      import android.widget.Button;
      import android.widget.EditText;
      import android.widget.TextView;
    
      public class NDKActivity extends Activity{
    
      Button buttonCalc;
      TextView result;
      EditText value1,value2;
      /** Called when the activity is first created. */
      MainActivity nativeLib;
      public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
     nativeLib = new MainActivity();
      String helloText = nativeLib.hello();
    
    result = (TextView) findViewById(R.id.result);
    value1 = (EditText) findViewById(R.id.value1);
    value2 = (EditText) findViewById(R.id.value2);
    
    // Update the UI
    TextView outText = (TextView) findViewById(R.id.textOut);
    outText.setText(helloText);
    
     // Setup the UI
    buttonCalc = (Button)this.findViewById(R.id.buttonCalc);
    
    buttonCalc.setOnClickListener(new OnClickListener() {
    
    
    public void onClick(View v) {
     int v1, v2, res = -1;
     v1 = Integer.parseInt(value1.getText().toString().trim());
     v2 = Integer.parseInt(value2.getText().toString().trim());
    
     res = nativeLib.add(v1, v2);
     result.setText(new Integer(res).toString());
     }
    
    
    
     });
     }
         }
    
  • 在命令提示符中运行 ndk-build

  • 进入项目目录-> 然后,输入此命令 <android-ndk-directory>\ndk-build.cmd 并回车

    完成后,我们可以在 obj 文件夹下检查 .so 文件。

    1. NDKActivity 的 XML 文件。

     <TextView android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Vikram"
    android:textSize="22sp"/>
    <TextView android:id="@+id/textOut"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Output"/>
    
    <EditText
    android:id="@+id/value1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:hint="Value 1"
    android:inputType="numberDecimal" />
    
     <TextView android:id="@+id/TextView01"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:text="+"
         android:textSize="36sp" />
    
          <EditText
       android:id="@+id/value2"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:hint="Value 2"
       android:inputType="numberDecimal" />
    
    <Button android:id="@+id/buttonCalc"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="=" />
    <TextView android:id="@+id/result"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="result"
       android:textSize="36sp" />
    
    
       </LinearLayout>
    

    @Vikram... 当我尝试运行 javah -classpath <project-name>/bin/classes;<ANDROID_SDK_HOME>\platforms\android-<xx>\android.jar -o HelloJNI.h com.example.test.MainActivity 时,控制台会显示以下异常信息:"main" java.lang.NullPointerException at sun.launcher.LauncherHelper.getMainClassFromJar(Unknown Source) at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source) - DJhon
    好的回答!谢谢你!只有一个关于Gradle项目的更正。在第7点中,我们应该用<project-name>\build\intermediates\classes\debug(或release)替换<project-name>/bin/classes。 - Pavlo28
    @GrafOrlov 我正在尝试运行这个命令,但是我无法运行第7步,它显示类未找到错误:无法找到'com.example.encrcytionexample.MainActivity'的类文件。我已经在Eclipse中完成了它。 - Research Development

    -1
    似乎是在 .h 文件和 .cpp 文件之间出现了函数不匹配的问题。 您在 .h 文件中提到了一些函数参数,在 native.cpp 文件的实现中缺失了这些参数。

    嗨Kirti,我搜索了我的参数但是找不到。谢谢回复。 - Kamal Bhardwaj

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接