个人博客系统

本文讨论的是在一个已经创建好的Android项目中通过添加JNI支持来使用C或C++代码,如果是新建项目,Android studio已经提供了简便的方式,只需要勾选 Include C++ Support 选项,便会自动给项目添加JNI环境,当然,前提是你已经安装了必要的组件,具体可以参考Android studio下JNI开发

20161029204834.png


下面就记录一下如何在一个已经创建好了的项目中搭建JNI环境。

  1. 1、打开一个已经创建好的项目

  2. 2、将项目切换到Project视图,在app/scr/main目录下,创建一个新的目录,比如cpp(或者其他名称)

  3. 20161029210327.png

  4. 3、cpp目录用来存放c或C++文件,可以在该目录下创建一个或多个c/c++文件,右键点击该目录,选择c/c++ source file选项,来创建文件,如下图(这里创建了两个c文件,HelloFromJNI提供一个函数用来返回字符串“hello from JNI”,SortFromJNI提供一个函数来实现简单的数组排序功能)

  5. 20161029210736.png

  6. 4、创建编译脚本(使用CMake或者NDK来编译库文件,只需配置其一就行

    如果是使用Android studio推荐的CMake来编译:

    1)、创建CMake脚本:和前面一样,先切换到project视图,右键点击 APP 目录,选择NEW-File,输入CMakeLists.txt,这样就在APP的根目录下创建了CMake脚本文件,文件内容如下

  1. #最低版本要求
    cmake_minimum_required(VERSION 3.4.1)
    
    #添加HelloFromJNI.c文件的预编译库
    add_library(    HelloFromJNI
                    SHARED
                    src/main/cpp/HelloFromJNI.c )
                    
    #添加SortFromJNI.c文件的预编译库
    add_library(    SortFromJNI
                    SHARED
                    src/main/cpp/SortFromJNI.c )
    
    find_library(   log-lib
                    log )

    1. 2)、关联本地库与Grande:打开app目录下的build.grande文件,添加如下配置:

    2. externalNativeBuild {
          cmake {
              path "CMakeLists.txt"
          }
      }

      其中path后面跟的CMakeLists.txt相对于build.grande文件的路径,请确保这两个文件都在APP目录下,截个图

    3. 20161029213226.png

    4. 如果使用NDK来编译:

      1. 1)在cpp目录下创建Android.mk和Application.mk文件,内容分别如下

  2. #Android.mk
    
    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE    := HelloFromJNI
    LOCAL_SRC_FILES := \
                HelloFromJNI.c \
                SortFromJNI.c \
    
    
    include $(BUILD_SHARED_LIBRARY)
#Application.mk
APP_ABI := all

    2)、配置build.grande文件

externalNativeBuild {
    ndkBuild {
        path file("src\\main\\cpp\\Android.mk")
    }
}

20161029225700.png

  5、实现对应的Java代码,具体参考Android中使用JNI的语法和规范

package cn.zhaoweihua.jnitest.jnitestpj;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
//实现如下功能:app启动后,将helloFromJNI函数返回的字符串显示在TextView中,点击界面排序按钮,调用sortFromJNI函数进行排序,
//同样将排序后的数组显示在TextVIew中,
public class MainActivity extends AppCompatActivity {

    TextView tv;
    //加载库文件
    static {
        System.loadLibrary("HelloFromJNI");
        System.loadLibrary("SortFromJNI");
    }
    //定义对应的native函数
    public native String helloFromJNI();
    public native void sortFromJNI(int[] arr, int len);
    
    //实现按钮点击事件
    public void sort(View view){
        //定义一个数组
        int[] arr = {12,5,48,23,111,985,45,10};
        //调用sortFromJNI函数实现数组排序
        sortFromJNI(arr, arr.length);
        //将排序后的数组显示在TextView中
        tv.setText(Arrays.toString(arr));
    }
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.tv);
        //界面加载后调用helloFromJNI函数,将返回的字符串显示在TextView中
        tv.setText(helloFromJNI());
    }
}

    对应的布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="cn.zhaoweihua.jnitest.jnitestpj.MainActivity">

    <TextView android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
    <Button android:onClick="sort"
        android:text="排序"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

  6、实现对应的c/c++代码,其中HelloFromJNI.c代码如下

//HelloFromJNI.c

#include <jni.h>

//返回字符串 “hello from JNI!!!”
jstring Java_cn_zhaoweihua_jnitest_jnitestpj_MainActivity_helloFromJNI(JNIEnv *env, jobject instance) {

    char* hello = "hello from JNI!!!";
    return (*env)->NewStringUTF(env, hello);
}

   SortFromJNI.c代码如下:

//SortFromJNI.c

#include <jni.h>

//实现简单冒泡排序
void bubbleSort(int *arr, int len){
    int i , j;
    for(i=0;i<len-1;i++){
        for(j=0; j<len-i-1; j++){
            if(arr[j]>arr[j+1]){
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
}
//调用bubbleSort函数进行排序
void Java_cn_zhaoweihua_jnitest_jnitestpj_MainActivity_sortFromJNI(JNIEnv *env, jobject instance,
        jintArray arr_, jint len) {

    jint *arr = (*env)->GetIntArrayElements(env, arr_, 0);
    bubbleSort(arr, len);
    (*env)->ReleaseIntArrayElements(env, arr_, arr, 0);
}

小技巧:使用Eclipse开发的时候,为了保证c/c++代码中native函数的函数名称正确,一般会使用jdk自带javah工具来生成对应的函数名,在Android studio中,无需再使用该工具,我们可以在java代码中先定义native方法,然后按alt+enter键错误修复功能,Android studio会自动帮我们在c文件中创建好对应的函数,这样就能省去很多麻烦。

20161029215915.png


  7、运行程序,验证结果

Screenshot_1477750595.png

启动app,TextView显示Hello from JNI!!!

Screenshot_1477750606.png

点击排序按钮,调用c文件的排序函数进行排序并将结果显示在TextView中



网站公告
这里是挨踢农民工的博客,欢迎光临,以上为一段测试信息。
生命在于折腾
博客分类
文章归档 更多
网站统计
当前在线人数:16
注册会员数:108
网站总浏览量:161859
文章总数:17
留言总数:9
评论总数:21
分类总数:6
友情链接总数:1