Tree結構:
local.properties
build.gradle
app/src/main/AndroidManifest.xml
app/src/main/jni/hello_jni.c
app/src/main/jni/hello_jni.h
app/src/main/jni/Android.mk
app/src/main/jni/Application.mk.mk
Compiler:
app/src/main/TestJni.java
app/src/main/MainActivity.java
project_name(testJni)/app/src/main
$ tree
.
├── AndroidManifest.xml
├── java
│ └── com
│ └── example
│ └── testjni
│ ├── FirstFragment.java
│ ├── MainActivity.java
│ ├── SecondFragment.java
│ └── TestJni.java
├── jni (必要,自行產生)
│ ├── Android.mk
│ ├── Application.mk
│ ├── hello_jni.c
│ └── hello_jni.h
├── jniLibs (必要, 從 libs拷貝資料夾過來)
│ ├── x86
│ │ └── libhello_jni.so
│ └── x86_64
│ └── libhello_jni.so
├── libs (ndk-build產生)
│ ├── arm64-v8a
│ │ └── libhello_jni.so
│ ├── x86
│ │ ├── gdbserver
│ │ ├── gdb.setup
│ │ └── libhello_jni.so
│ └── x86_64
│ ├── gdbserver
│ ├── gdb.setup
│ └── libhello_jni.so
...
...
...
...
project_name(testJni)/
$ tree
├── gradle.properties
├── local.properties
local.properties
sdk.dir=/opt/android_studio/sdk
ndk.dir=/opt/android_studio/sdk/ndk/20.1.5948944/ (官方建議寫在 build.gradle)
build.gradle
android {
compileSdkVersion 28
buildToolsVersion '28.0.3'
...
...
ndkVersion "20.1.5948944"
}
app/src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testjni"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="26" />
app/src/main/jni/hello_jni.c
#include <jni.h>
#include <stdio.h>
#include <android/log.h>
#include "hello_jni.h"
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "TAG", __VA_ARGS__);
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, "TAG", __VA_ARGS__);
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, "TAG", __VA_ARGS__);
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "TAG", __VA_ARGS__);
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "TAG", __VA_ARGS__);
// Java_pacakgeName_className_functionName
JNIEXPORT jstring JNICALL Java_com_example_testjni_TestJni_getString(JNIEnv * env, jobject obj, jstring s)
{
char * st = (char *) (*env)->GetStringUTFChars(env, s, 0);
LOGI("\n c-string: %s", st);
char * str = "hello_world";
jstring rtn;
rtn = (*env)->NewStringUTF(env, str);
return rtn;
}
app/src/main/jni/hello_jni.h
#ifndef TESTJNI_HELLO_JNI_H
#define TESTJNI_HELLO_JNI_H
JNIEXPORT jstring JNICALL Java_com_example_testjni_TestJni_getString(JNIEnv * env, jobject obj, jstring s);
#endif //TESTJNI_HELLO_JNI_H
app/src/main/jni/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello_jni
LOCAL_SRC_FILES := hello_jni.c
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
include $(BUILD_SHARED_LIBRARY)
app/src/main/jni/Application.mk.mk
APP_ABI := x86 (x86電腦的emulator用。本來用x86_64,但編譯時說找不到@@)
APP_PLATFORM := android-16
APP_STL := c++_shared
app_abi
Compiler:
$ cd path/testJni/app/src/main/jni
$ ndk-build
在/usr/local/bin產生個ndk-build的script
#!/bin/sh
#DIR="$(cd "$(dirname "$0")" && pwd)"
DIR="/opt/android_studio/sdk/ndk/20.1.5948944/"
$DIR/build/ndk-build "$@"
成功後,會產生libs和obj資料夾
將 libs/abi 資料夾拷貝到 jniLibs
app/src/main/TestJni.java
package com.example.testjni;
public class TestJni {
public native String getString(String str);
static {
System.loadLibrary("hello_jni");
}
}
app/src/main/MainActivity.java
package com.example.testjni;
import android.os.Bundle;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends AppCompatActivity {
TestJni tj = new TestJni();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Log.i("test_hello", "Start jni");
Log.i("test_nello", "jni="+tj.getString("hello_jni"));
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
...
...
...
這樣應該可以在emulator上執行了,開啟logcat應該看得到jni的輸出
bsp code (system/core/rootdir/etc/public.libraries.android.txt)
...
...
libstdc++.so
libsync.so
libvulkan.so
libwebviewchromium_plat_support.so
libz.so
libhello_jni.so 添加
ref:
內置應用so庫無法打開問題解決
AndroidStudio NDK開發【dlopen failed: library "libc++_shared.so" not found】報錯解決
沒有留言:
張貼留言