我开始学习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'
}
我的应用程序结构如下:
到目前为止,一切都很完美。应用程序运行并给我预期的结果。现在我想要的是 - 创建新项目并使用上面的项目.so文件,所以在我的新项目中我不想再次编写c ++逻辑。为此,我计划在该目录中创建一个新项目作为jniLibs并复制上述项目的.so文件。但我没有在上面的项目中获得.so文件。当我提取上述项目的apk文件时,我只得到一个so文件。
任何建议和答案将不胜感激。提前谢谢。
答案 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 ,并会可靠地显示您文件的内容。