本文源码:https://github.com/jt1024/JNIBasicForAndroid
环境
1.Android Studio 3.0
2.gradle-4.1-all
3.android sdk 26
一、在Android Studio 新建安卓工程
二、基本配置
参照:
JNI/NDK编程(一)——无参函数之Hello world !
JNI/NDK编程(二)——带参函数之模拟登录
JNI/NDK编程(三)——C 调用 Java 成员变量
三、编写代码
1.编写C++文件 login_lib.cpp
路径:NDKFourthDemo/app/src/main/cpp/login_lib.cpp
#include
#include "string.h"
extern "C" JNIEXPORT void JNICALL
Java_com_tao_ndkfourthdemo_Java2CLogin_login(JNIEnv *env, jobject instance, jstring username, jstring password, jint authcode) {
jclass jclazz;
//1.加载java类得到class对象
jclazz = env->FindClass("com/tao/ndkfourthdemo/Java2CLogin");
//2.获取java类的函数
//2.1 通过实例对象获取实例方法ID
jmethodID showMessage = env->GetMethodID(jclazz, "showMessage", "(Ljava/lang/String;)V");
if (authcode == 888) {
const char *cStr;
const char *pStr;
jboolean isCopy;
cStr = env->GetStringUTFChars(username, &isCopy);
pStr = env->GetStringUTFChars(password, &isCopy);
int reUsername = strcmp(cStr, "admin");
int rePassword = strcmp(pStr, "1234");
if (reUsername == 0 && rePassword == 0) {
//2.2 通过方法ID调用实际的Java方法
env->CallVoidMethod(instance, showMessage, env->NewStringUTF("登陆成功!"));
} else {
env->CallVoidMethod(instance, showMessage, env->NewStringUTF("用户名或密码错误!"));
}
} else {
env->CallVoidMethod(instance, showMessage, env->NewStringUTF("验证码错误!"));
}
}
extern "C" JNIEXPORT void JNICALL
Java_com_tao_ndkfourthdemo_Java2CLogin_jniNullFunc(JNIEnv *env, jobject instance) {
jclass jclazz;
jclazz = env->FindClass("com/tao/ndkfourthdemo/Java2CLogin");
jmethodID nullFunc = env->GetMethodID(jclazz, "nullFunc", "()V");
env->CallVoidMethod(instance, nullFunc);
}
extern "C" JNIEXPORT void JNICALL
Java_com_tao_ndkfourthdemo_Java2CLogin_jniIntFunc(JNIEnv *env, jobject instance) {
jclass jclazz;
jclazz = env->FindClass("com/tao/ndkfourthdemo/Java2CLogin");
jmethodID intFunc = env->GetMethodID(jclazz, "intFunc", "(II)I");
env->CallVoidMethod(instance, intFunc, 21, 12);
}
extern "C" JNIEXPORT void JNICALL
Java_com_tao_ndkfourthdemo_Java2CLogin_jniStringFunc(JNIEnv *env, jobject instance) {
jclass jclazz;
jclazz = env->FindClass("com/tao/ndkfourthdemo/Java2CLogin");
jmethodID stringFunc = env->GetMethodID(jclazz, "stringFunc", "(Ljava/lang/String;)V");
env->CallVoidMethod(instance, stringFunc, env->NewStringUTF("hello jni"));
}
extern "C" JNIEXPORT void JNICALL
Java_com_tao_ndkfourthdemo_Java2CLogin_jniStaticFunc(JNIEnv *env, jobject instance) {
jclass jclazz;
jclazz = env->FindClass("com/tao/ndkfourthdemo/Java2CLogin");
jmethodID staticFunc = env->GetStaticMethodID(jclazz, "staticFunc", "()V");
env->CallStaticVoidMethod(jclazz, staticFunc);
}
extern "C" JNIEXPORT void JNICALL
Java_com_tao_ndkfourthdemo_Java2CLogin_anotherFunc(JNIEnv *env, jobject instance) {
jclass jclazz;
jclazz = env->FindClass("com/tao/ndkfourthdemo/AnotherJava2CLogin");
jmethodID showMessage = env->GetMethodID(jclazz, "showMessage", "()V");
jobject dpobj = env->AllocObject(jclazz);//如果C调用的Java方法不在一个类中,则使用这行代码
env->CallVoidMethod(dpobj, showMessage);
}
2.编写Jave文件 Java2CLogin
路径:NDKFourthDemo/app/src/main/java/com.tao.ndkfourthdemo.Java2CLogin
package com.tao.ndkfourthdemo;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
/**
* 作者: 麦典威
* 修改时间:2018/3/15 8:07
* 版权声明:www.ekwing.com
* 功能: ${TODO}
*/
public class Java2CLogin {
private static final String TAG = "Java2CLogin";
private Context mContext;
static {
System.loadLibrary("login_lib");
}
/**
* 带参数的 native 函数
*
* @param username 用户名
* @param password 密码
* @param authcode 验证码
* @return
*/
public native void login(String username, String password, int authcode);
public Java2CLogin(Context mContext) {
this.mContext = mContext;
}
public void showMessage(final String msg) {
Log.e(TAG, "jt——>C调用了java的 showMessage 函数——>" + msg);
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(mContext, msg, Toast.LENGTH_LONG).show();
}
});
}
public native void jniNullFunc();
public native void jniIntFunc();
public native void jniStringFunc();
public native void jniStaticFunc();
public native void anotherFunc();
//C调用java中的空方法
public void nullFunc() {
Log.e(TAG, "C调用java中的空方法");
}
//C调用java中的带两个int参数的方法
public int intFunc(int x, int y) {
Log.e(TAG, "C调用java中的带两个int参数的方法——>x + y=" + (x + y));
return x + y;
}
//C调用java中参数为string的方法
public void stringFunc(String s) {
Log.e(TAG, "C调用java中参数为string的方法——>s=" + s);
}
//C调用java的静态方法
public static void staticFunc() {
Log.e(TAG, "C调用java的静态方法");
}
}
3.编写Jave文件 AnotherJava2CLogin
路径:NDKFourthDemo/app/src/main/java/com.tao.ndkfourthdemo.AnotherJava2CLogin
package com.tao.ndkfourthdemo;
import android.util.Log;
/**
* 作者: 麦典威
* 修改时间:2018/3/22 10:21
* 版权声明:www.ekwing.com
* 功能: ${TODO}
*/
public class AnotherJava2CLogin {
private static final String TAG = "AnotherJava2CLogin";
public void showMessage() {
Log.e(TAG, "jt——>native与java方法不在一个类时,C调用java的方法");
}
}
4.编写Activity文件 MainActivity
路径:NDKFourthDemo/app/src/main/java/com.tao.ndkfourthdemo.MainActivity
package com.tao.ndkfourthdemo;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private EditText edtUsername, edtPassword, edtAuthcode;
private Button btnLogin, btn_jni1, btn_jni2, btn_jni3, btn_jni4, btn_jni5;
private Java2CLogin java2CLogin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
java2CLogin = new Java2CLogin(MainActivity.this);
initView();
}
private void initView() {
edtUsername = findViewById(R.id.edt_username);
edtPassword = findViewById(R.id.edt_password);
edtAuthcode = findViewById(R.id.edt_authcode);
btnLogin = findViewById(R.id.btn_login);
btn_jni1 = findViewById(R.id.btn_jni1);
btn_jni2 = findViewById(R.id.btn_jni2);
btn_jni3 = findViewById(R.id.btn_jni3);
btn_jni4 = findViewById(R.id.btn_jni4);
btn_jni5 = findViewById(R.id.btn_jni5);
btnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String username = edtUsername.getText().toString().trim();
String password = edtPassword.getText().toString().trim();
String authcodeStr = edtAuthcode.getText().toString().trim();
int authcode = Integer.parseInt(authcodeStr.equals("") ? "0" : authcodeStr);
java2CLogin.login(username, password, authcode);
}
});
btn_jni1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
java2CLogin.nullFunc();
}
});
btn_jni2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
java2CLogin.jniIntFunc();
}
});
btn_jni3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
java2CLogin.jniStringFunc();
}
});
btn_jni4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
java2CLogin.staticFunc();
}
});
btn_jni5.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
java2CLogin.anotherFunc();
}
});
}
}
5.编写 activity_main.xml
6.编写CMakeLists.txt文件,以后如果编写其他jni类,只需替换里面的“login_lib”
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
login_lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/login_lib.cpp )
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
login_lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
四、编译
点击build——>Rebuild Project 或 Make Progject
参照:
JNI/NDK编程(一)——无参函数之Hello world !
JNI/NDK编程(二)——带参函数之模拟登录
JNI/NDK编程(三)——C 调用 Java 成员变量
五、运行程序
附:JNI/NDK编程基础系列导航
JNI/NDK编程(一)——无参函数之Hello world !
JNI/NDK编程(二)——带参函数之模拟登录
JNI/NDK编程(三)——C 调用 Java 成员变量
JNI/NDK编程(四)——C 调用 Java 类中的函数/方法
JNI/NDK编程(五)——通过打印日志debug
JNI/NDK编程(六)——综合实战:通过编译lame实现wav转mp3