在android studio中创建.so文件,并在Android中的另一个应用程序中使用它

时间:2018-03-27 09:59:27

标签: android c++ android-ndk ndk-build

我开始学习android ndk。我是新手。我使用添加c ++支持在Android studio 3.0.1中创建了一个项目。在此应用程序中,用户在活动中输入数字,并使用c ++代码告知其是否为素数。这是我的活动代码:

package com.app.androidkt.samplendk;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {


EditText number_chk;
Button result_btn;


// Used to load the 'native-lib' library on application startup.
static {
    System.loadLibrary("native-lib");
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    result_btn = (Button)findViewById(R.id.result_btn);
    number_chk = (EditText) findViewById(R.id.number_chk);
    final TextView tv = (TextView) findViewById(R.id.sample_text);



    result_btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            int number;
            try{
                number = Integer.parseInt(number_chk.getText().toString());
                tv.setText(isPrimeNumber(number));
            }
            catch (Exception e)
            {
                tv.setText("Please enter valid number");
            }
        }
    });

    // Example of a call to a native method


}

/**
 * A native method that is implemented by the 'native-lib' native library,
 * which is packaged with this application.
 */
//public native String stringFromJNI();
private native String isPrimeNumber(int number);
}

我的native-lib.cpp就像:

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

extern "C"
JNIEXPORT jstring

JNICALL

Java_com_app_androidkt_samplendk_MainActivity_isPrimeNumber(
    JNIEnv *jenv,
    jobject self,
    jint number)
{
std::string result = "Prime Number";
int i;
for(i = 2; i <= number / 2; ++i)
{
    if(number % i == 0)
    {
        result = "Not a Prime Number";
        break;
    }
}
return jenv->NewStringUTF(result.c_str());
}

我的app.gradle如下所示,我没有改变任何内容:

apply plugin: 'com.android.application'

android {
compileSdkVersion 26
defaultConfig {
    applicationId "com.app.androidkt.samplendk"
    minSdkVersion 15
    targetSdkVersion 26
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    externalNativeBuild {
        cmake {
            cppFlags ""
        }
    }
}
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
externalNativeBuild {
    cmake {
        path "CMakeLists.txt"
    }
   }
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}

我的应用程序结构如下:

enter image description here

到目前为止,一切都很完美。应用程序运行并给我预期的结果。现在我想要的是 - 创建新项目并使用上面的项目.so文件,所以在我的新项目中我不想再次编写c ++逻辑。为此,我计划在该目录中创建一个新项目作为jniLibs并复制上述项目的.so文件。但我没有在上面的项目中获得.so文件。当我提取上述项目的apk文件时,我只得到一个so文件。

  1. 那么如何为上面的项目创建.so文件
  2. 如何在另一个项目中使用此.so文件
  3. 任何建议和答案将不胜感激。提前谢谢。

1 个答案:

答案 0 :(得分:1)

最佳做法是不在MainActivity类中创建本机方法。如果您为isPrimeNumber()和可能的其他原生方法创建单独的小类,则分享您的工作会更容易。

在您的情况下,该方法可以声明为static,因为它不依赖于调用它的Java对象。原生静态方法具有更好的性能,并且 - 再次 - 更容易共享。

Android Studio将所有内置libnative-lib.so文件放在 app / build / intermediates 目录中。您将在不同的子目录中找到 fat <​​/ em>库以及较小的剥离的文件。您可以将较小的副本复制到第二个项目的 jniLibs 目录。

如果您的C ++使用共享STL库,例如libgnustl_shared.so,您还必须将其复制到第二个项目的 jniLibs 目录。

我们经常通过在gradle脚本中定义 abiFilters 来限制我们构建的本机库的变体。您在上面发布的脚本没有任何功能,从表面上看,它不会创建拆分APK,因此我无法解释为什么您在APK中只看到一个libnative-lib.so

请注意, mips 设备目前不存在, armeabi (旧的v6变体)也非常罕见。最新的NDK提醒说,这些ABI不会长期得到支持。

顺便说一下,您不需要将其重命名为ZIP:Android Studio在其菜单中分析APK ,并会可靠地显示您文件的内容。