作为一名安卓程序员,起初都是从入门->初级程序员->中级程序员->高级程序员->资深程序员->再到专家这一过程的,当然也不排除有些人从入门到放弃啦,哈哈,开个玩笑。如果想成为一名高级程序员,最起码的,什么三方框架源码呀、高级UI、移动架构、NDK等技术还是要熟练,不然不会的话,人家就给你带上了个中级程序的称号。接下来废话不多说,进入今天的博客主题吧。
今天我们来学习下NDK开发最基础的一个技术,大家知道开发安卓app无非就是用java代码进行应用层开发了,当然最近Google官方宣称可以用Kotlin语言啦,除此之外之前的一份工作经历竞然还有QT开发安卓,有点醉醉的。开发应用层app,java只能用于应用层,还是比较有局限性的。那java代码能否调用C代码呢,答案当然是可以的。
Java代码能否直接调用C代码呢?当然不可以,我们需要用动态连接库来作为中转,什么意思呢?其实也就是将你写好的C代码转换成动态链接库,然后供给java代码调用,大体是这样的一个流程。接下我分别讲述之:
一、Java层代码
package com.wufq.myfirstndk;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import android.app.Activity;
public class MainActivity extends Activity implements OnClickListener {
private Button operateBtn;
static{
System.loadLibrary("hello");
}
public native String helloFromJni();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
operateBtn = (Button) findViewById(R.id.btn);
operateBtn.setOnClickListener(this);
}
@Override
public void onClick(View arg0) {
switch (arg0.getId()) {
case R.id.btn:
String text = helloFromJni();
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
break;
}
}
}
其中,看到上面的代码块,最主要的就是有个静态代码块跟java本地方法啦,System,loadLibarary();括号里面的参数就是动态链接库的名字啦,public native String helloFromJni();这是个java的本地方法,也就是调用它的话,它会去动态链接库里加载对应的C代码方法。
二、C代码
#include<stdio.h>
#include<jni.h>
jstring Java_com_wufq_myfirstndk_MainActivity_helloFromJni(JNIEnv* env,jobject obj){
char *cstr = "hello,Good!!!";
jstring jstr = (*env)->NewStringUTF(env,cstr);
return jstr;
}
这是C代码,第一、二两行是C代码的头文件,这里相信大家应该都理解,就不作详细解说了。下面有个C代码的方法,一看不就是跟Java代码里相似吗?其实这必定会相似的,因为C代码方法的书写流程要跟java代码的本地方法保持一致。jstrng是c代码的字符串,对应开java的String,然后Java_com_wufq_myfirstndk_MainActivity_helloFromJni这名命名的话是由Java+应用层的包名+类名+方法名,以下划线替换点写出来的;方法的两参数分别为JNIEnv*及jobject,JNIEnv*是jni.h文件中主要的一个类,jobject类似于java的祖先对象Object;在方法中,我们定义了一个char* cstr的C代码字符串,然后我们要返回给java使用,这里不可以直接返回,我们借助了(*env)->NewStringUTF(env,cstr)来转换成jstring,这里可以参考JNINativeInterface结构体的调用流程,最后返回这个jstring.
三、Android.mk文件的编写
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello
LOCAL_SRC_FILES := Hello.c
include $(BUILD_SHARED_LIBRARY)
各参数解释:LOCAL_PATH——调用当前目录
CLEAR_VARS——清除之前的配置vars
LOCAL_MODULE——生成动态链接库的名称
LOCAL_SRC_FILES——编译的C代码文件
BUILD_SHARED_LIBRARY——生成动态链接库,其中如果要生成静态链接库的话,可改成BUILD_STATIC_LIBRARY
四、编译生成动态链接库
当然你得先配置好开发环境,这里用cygwin+ndk,打开cyginwin进入到jni目录,对其执行ndk-build命令,即可生成动态链接库,如下图所示:
最后你就可以运行啦,运行结果如下:
1、效果一:
2、效果二:
好啦,最简单的java调用 C代码就这么简单啦,写得不对的地方欢迎批评指正,谢谢!