Android NDK开发(一)之java层调用C代码浅析

作为一名安卓程序员,起初都是从入门->初级程序员->中级程序员->高级程序员->资深程序员->再到专家这一过程的,当然也不排除有些人从入门到放弃啦,哈哈,开个玩笑。如果想成为一名高级程序员,最起码的,什么三方框架源码呀、高级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代码就这么简单啦,写得不对的地方欢迎批评指正,谢谢!

猜你喜欢

转载自blog.csdn.net/wufeiqing/article/details/75206226
今日推荐