天天看点

windows+as+ndk建立jni工程例子

由于编写demo的需要,了解了一下jni接口的实现。本文适合像我熟悉c++却对安卓比较小白速度上手jni。

总体流程

我们搞定c++模块后希望在android层被调用,但实际上接口需要在android层先定好,然后根据android层的接口再转化成jni接口,然后在这些jni接口里使用我们的c++模块代码。可以用中间生成的文件来表示这个流程:

test.java -> test.class -> test.h –> test.c

最后在test.c里面调用我们的c++代码。

准备

如果不够详细,百度可以了,下面那些都很常见的操作。

1. 需要安装一个android studio

2. 配置jdk环境

我们可以直接使用android studio自带的jre。在安装目录下就有(例如我的D:\Android\Android Studio\jre)

在windows上配置以下3个环境变量

JAVA_HOME   D:\Android\Android Studio\jre
CLASSPATH   %JAVA_HOME%\lib
Path   %JAVA_HOME%\bin
           

path一般已经有的,在后面添加就好了。

3. 配置ndk环境

https://www.jianshu.com/p/708e6bf68ae9

4.建两个目录来分别存放as项目和so生成项目

windows+as+ndk建立jni工程例子

java层接口

我们先用as建立一个工程放在jni-as下。

windows+as+ndk建立jni工程例子

然后建立一个java类,这个就是java层的接口了。

package com.test.jnitest;

/**
 * Created by Administrator on 2018/3/26.
 */

public class jnitestimpl {
    static {
        System.loadLibrary("jnitest");   //defaultConfig.ndk.moduleName
    }
    public native String getVersionString();
}
           

jnitest是你之后要生成的so库名

我在这先定一个简单的接口函数getVersionString,作用是返回一个版本号

然后在MainActivity里面使用它

package com.test.jnitest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private TextView tv_version_;
    private jnitestimpl jti_;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tv_version_ = (TextView) this.findViewById(R.id.tv_version);

        jti_ = new jnitestimpl();

        tv_version_.setText(jti_.getVersionString());
    }
}
           

可以把自建的helloworld text元素带上id tv_version,或者你再建一个。

然后build。

生成对应的c++头文件

build完后,jni-as\app\build\intermediates\classes\debug\com\test\jnitest\jnitestimpl.class就是java接口类生成的class文件,可以用这个来生成对应的c++头文件。

在jni-ndk下建立一个jni文件夹,打开命令行cd到这目录执行

会生出一个头文件内容为

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_test_jnitest_jnitestimpl */

#ifndef _Included_com_test_jnitest_jnitestimpl
#define _Included_com_test_jnitest_jnitestimpl
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_test_jnitest_jnitestimpl
 * Method:    getVersionString
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_test_jnitest_jnitestimpl_getVersionString
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
           

ndk-build出so文件

利用上步生成的头文件我们可以创建一个cpp文件(起名jnitestimpl.cpp)来实现接口函数

//jnitestimpl.cpp
#include "com_test_jnitest_jnitestimpl.h"

JNIEXPORT jstring JNICALL Java_com_test_jnitest_jnitestimpl_getVersionString(JNIEnv *env, jobject obj){
     return env->NewStringUTF("jnitest 0.0.1");  
}
           

jni目录下,建立两个ndk-build的配置文件:Android.mk Application.mk

Android.mk

# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := jnitest
LOCAL_SRC_FILES := jnitestimpl.cpp

include $(BUILD_SHARED_LIBRARY)
           

Application.mk

#APP_ABI := all
APP_ABI := armeabi armeabi-v7a
#APP_PLATFORM := android-21
           

关于这些ndk-build的文档说明,可参考ndk安装目录下的docs。

看一下目录下的东西:

windows+as+ndk建立jni工程例子

然后在jni-ndk目录下执行

完成后可在jni-ndk\libs下看到生成的so了。

好了,该生产的都搞定了,接下来配置一下就可以运行app了。

as项目编译运行

将以上生成的jni-ndk\libs复制到-jni-as\app\libs。

在app的build.gradle中添加

windows+as+ndk建立jni工程例子

然后同步一下as项目。

Run app,搞定!!!

windows+as+ndk建立jni工程例子

继续阅读