我开始学习 android ndk。我是新来的。我在 Android studio 3.0.1 中使用添加 c++ 支持创建了一个项目。在此应用程序中,用户在 Activity 中输入数字并使用 C++ 代码判断其是否为质数。这是我的 Activity 代码:
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'
}
我的应用程序结构是这样的:
到目前为止,一切都很完美。应用程序运行并给我预期的结果。现在我想要的是 - 创建新项目并使用上面的项目 .so 文件,所以在我的新项目中我不想再次编写 C++ 逻辑。为此,我计划在该添加目录中创建一个新项目作为 jniLibs 并复制上述项目的 .so 文件。但是我没有在上面的项目中得到 .so 文件。当我提取上述项目的 apk 文件时,我只得到一个 so 文件。
- 那么如何为上述项目创建.so文件
- 如何在另一个项目中使用这个.so文件
任何建议和回答将不胜感激。提前致谢。
最佳答案
最佳做法是不要在 MainActivity 类中创建 native 方法。如果您为 isPrimeNumber()
和可能的其他 native 方法创建一个单独的小类,共享您的工作会更容易。
在您的情况下,该方法可以声明为 static
,因为它不依赖于调用它的 Java 对象。 native 静态方法具有更好的性能,并且再次更易于共享。
Android Studio 将所有构建的 libnative-lib.so
文件放在 app/build/intermediates 目录中。您会在不同的子目录中找到 fat 库以及较小的、stripped 的文件。小的可以复制到第二个工程的jniLibs目录下
如果您的 C++ 使用共享的 STL 库,例如libgnuSTL_shared.so
,你还必须将它复制到第二个项目的jniLibs目录下。
我们经常通过在 gradle 脚本中定义 abiFilters 来限制我们构建的原生库的变体。您在上面发布的脚本没有任何功能,从表面上看,它不会创建拆分 APK,因此我无法解释为什么您在 APK 中只看到一个 libnative-lib.so
。
请注意,目前mips 设备并不存在,armeabi(旧的 v6 变体)也极为罕见。最新的 NDK 提醒这些 ABI 不会被长期支持。
顺便说一句,您不需要将其重命名为 ZIP:Android Studio 的菜单中有Analyze APK,并且会可靠地向您显示文件的内容。
关于android - 在android studio中创建.so文件并在Android中的另一个应用程序中使用它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49509856/