package com.example.register;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
private static final String TAG = "HTC+++";
public int age;
static {
System.loadLibrary("hello-jni");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initData();
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(this);
}
private void initData() {
age = 10;
}
private void calledByNative() {
Log.d(TAG, "java layer: called By Native");
}
private static void staticMethod(int value) {
Log.d(TAG, "java layer: static method called By Native. value: "
+ value);
}
private int multi(int a, int b) {
return a * b;
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.button:
print("I want to print");
int result = add(123, 456);
Log.d(TAG, "123 + 456 = " + result);
String s = getString();
Log.d(TAG, "getString() = " + s);
callJava();
changeintField(111);
Log.d(TAG, "age:" + age);
break;
default:
break;
}
}
private native void print(String str);
private native int add(int a, int b);
private native String getString();
private native void callJava();
private native void changeintField(int value);
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context="${relativePackage}.${activityClass}" >
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="xxxx" />
</LinearLayout>
// jni/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := dynamic_jni.c \
static_jni.c
LOCAL_LDLIBS :=-llog
include $(BUILD_SHARED_LIBRARY)
// jni/Application.mk
APP_ABI := all
// jni/dynamic_jni.c
#include <string.h>
#include <jni.h>
#include <android/log.h>
#define LOG_TAG "HTC+++"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__)
void callJavaMethod(JNIEnv *env, jobject thiz) {
jclass cls = (*env)->GetObjectClass(env, thiz);
jmethodID methodId = (*env)->GetMethodID(env, cls, "calledByNative", "()V");
(*env)->CallVoidMethod(env, thiz, methodId);
jmethodID staticMethod = (*env)->GetStaticMethodID(env, cls, "staticMethod", "(I)V");
(*env)->CallStaticVoidMethod(env, cls, staticMethod, 999);
jmethodID multiMethod = (*env)->GetMethodID(env, cls, "multi", "(II)I");
jint result = (*env)->CallIntMethod(env, thiz, multiMethod, 100, 200);
LOGD("multi: 100 * 200 = %d", result);
}
void changeIntField(JNIEnv *env, jobject thiz, jint newValue) {
jclass cls = (*env)->GetObjectClass(env, thiz);
jfieldID fieldId = (*env)->GetFieldID(env, cls, "age", "I");
jint age = (*env)->GetIntField(env, thiz, fieldId);
LOGD("Native: current age:%d", age);
(*env)->SetIntField(env, thiz, fieldId, newValue);
}
void nativePrint(JNIEnv *env, jobject thiz, jstring jstr) {
const char *nativeString = (*env)->GetStringUTFChars(env, jstr, 0);
LOGD("nativePrint() String:%s", nativeString);
//java中有垃圾回收机制,而c语言没有,那么使用完该字符串之后该如何处理呢?
//字符串str使用完后,需要通知虚拟机平台相关代码无需再访问
//如果是中文则需要转码
(*env)->ReleaseStringUTFChars(env, jstr, nativeString);
}
jint nativeAdd(JNIEnv *env, jobject thiz, jint a, jint b) {
return a + b;
}
/*
jstring newString(JNIEnv *env, jobject thiz) {
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
*/
static JNINativeMethod gMethods[] = {
{"print", "(Ljava/lang/String;)V", (void*) nativePrint },
{"add", "(II)I", (void*) nativeAdd },
// {"getString", "()Ljava/lang/String;", (void*) newString },
{"callJava", "()V", (void*) callJavaMethod },
{"changeintField", "(I)V", (void*) changeIntField }
};
static int registerMethods(JNIEnv * env) {
jclass clazz = (*env)->FindClass(env, "com/example/register/MainActivity");
int size = sizeof(gMethods) / sizeof(gMethods[0]);
if ((*env)->RegisterNatives(env, clazz, gMethods, (jint) size) != JNI_OK) {
return -1;
}
return 0;
}
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv* env = NULL;
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return -1;
}
if (registerMethods(env) != 0) {
return -1;
}
return JNI_VERSION_1_4;
}
// static_jni.c
#include <string.h>
#include <jni.h>
#include <android/log.h>
#define LOG_TAG "MainActivity"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__)
jstring Java_com_example_register_MainActivity_getString(JNIEnv* env,
jobject thiz) {
return (*env)->NewStringUTF(env, "Hello from static JNI !");
}